diff --git a/.azuredevops/ado/deploy-template-sub.yml b/.azuredevops/ado/deploy-template-sub.yml new file mode 100644 index 000000000..6d308154e --- /dev/null +++ b/.azuredevops/ado/deploy-template-sub.yml @@ -0,0 +1,83 @@ +parameters: + - name: location + - name: templateFile + - name: workingDir + type: string + - name: deployOperation + type: string + default: 'create' + - name: parameterArray + type: object + default: [] + - name: jobName + default: Deploy_Bicep_Main_Module_Sub_level + - name: preDeploySteps + type: stepList + default: [] + - name: postDeploySteps + type: stepList + default: [] + - name: variableOverrides + type: object + default: {} + +jobs: + - job: ${{ parameters.jobName }} + displayName: Deploy ${{ parameters.templateFile }} + variables: + ${{ insert }}: ${{ parameters.variableOverrides }} + + steps: + - ${{ parameters.preDeploySteps }} + + - task: PowerShell@2 + displayName: Converting parameters array + inputs: + targetType: 'inline' + script: | + $myArray = ConvertFrom-Json $Env:PARAMETER_ARRAY + # Need to add depth for embedded json arrays. + $jsonmyArray = $myArray | ConvertTo-Json -Compress -Depth 100 + Write-Host "json_my_Array is: $jsonmyArray" + # Converting into json into hash array to extract the string array + $hasharray=@{} + $jsonObjmyArray= ConvertFrom-Json $jsonmyArray + foreach ( $property in $jsonObjmyArray.PSObject.Properties ) { + $hasharray[$property.Name]=$property.Value + } + # Getting values from the hash array into string array + $stringmyArray=@() + foreach ($parameter in $hasharray.SyncRoot) { + $stringmyArray += $parameter + } + Write-Host "Here is our string array: $stringmyArray" + # Formatting for the bicep deployment + $stringparameterArray=@() + foreach ( $string in $stringmyArray) { + $string1 = $string -replace ' ', '=' + $stringparameterArray += $string1 + } + Write-Host "Here is final format of parameters for deployment with Bicep" + $stringparameterArray + $stringparameters=[string]::Join(" ", $stringparameterArray) + $stringparameters + Write-Host "##vso[task.setvariable variable=bicep_parameters]$stringparameters" + env: + PARAMETER_ARRAY: ${{convertToJson(parameters.parameterArray)}} + + - task: AzureCLI@2 + displayName: Resource deployment at subscription scope + inputs: + azureSubscription: $(serviceConnection) + scriptType: 'bash' + scriptLocation: 'inlineScript' + inlineScript: | + $(var-bashPreInjectScript) + ls + echo "Deploying ${{ parameters.templateFile }} using ${{ parameters.deployOperation}} operation..." + az deployment sub ${{ parameters.deployOperation }} \ + --location ${{ parameters.location }} \ + --name $(Build.BuildNumber) \ + --template-file ${{ parameters.templateFile}} \ + --parameters $(bicep_parameters) + workingDirectory: ${{ parameters.workingDir }} diff --git a/.azuredevops/ado/main-ado-avd-accelerator.yml b/.azuredevops/ado/main-ado-avd-accelerator.yml new file mode 100644 index 000000000..89421bf69 --- /dev/null +++ b/.azuredevops/ado/main-ado-avd-accelerator.yml @@ -0,0 +1,85 @@ +trigger: + - none + +pr: + - none + +variables: + - name: deploymentRegion + value: canadacentral + - name: serviceConnection + value: AzureLabCACN-Sponosored + - name: vmWinImage + value: windows-latest + - name: vmImage + value: ubuntu-latest + - name: deployOperation + value: create + - name: var-bashPostInjectScript + value: ':' + - name: var-bashPreInjectScript + value: 'set -E; function catch { echo "##vso[task.logissue type=error]Caller: $(caller), LineNo: $LINENO, Command: $BASH_COMMAND" ; exit 1 ; } ; echo ; echo "Current working directory: $(pwd)" ; echo ; trap catch ERR' + - name: avdShrdlSubsId + value: a165ed8a-0e83-46f1-9994-b216229c2da7 + - name: avdWrklSubsId + value: a165ed8a-0e83-46f1-9994-b216229c2da7 + - name: avdWrklSecretAccess + value: 8e23a491-5178-4c69-9fce-1377e52a29c6 + - name: createAvdVnet + value: false + - name: useSharedImage + value: false + - name: avdOsImage + #value: win11_21h2_office + #value: win10_21h2 + value: win10_21h2_office + #value: win11_21h2 + - name: avdIdentityDomainName + value: azureminilab.com + - name: avdDomainJoinUserName + value: 'azadmin@azureminilab.com' + - name: avdDomainJoinUserPassword + value: '!V0ipc@123' + - name: avdVmLocalUserName + value: azadmin + - name: avdVmLocalUserPassword + value: '!R37fallacy1505' + + +stages: + - stage: Deploy_AVD_Accelerator + displayName: Deploy AVD Accelerator + jobs: + # Deploy template deploy-baseline.bicep for AVD Accelerator + - template: deploy-template-sub.yml + parameters: + jobName: Deploy_AVD_Accelerator + location: $(deploymentRegion) + workingDir: $(System.DefaultWorkingDirectory)/workload + templateFile: deploy-baseline.bicep + parameterArray: + - deploymentPrefix 'app1' + - avdDeploySessionHostsCount 1 + - avdWorkloadSubsId $(avdWrklSubsId) + - avdEnterpriseAppObjectId '82205950-fef1-4f88-8801-86e60c2e9318' + - avdManagementPlaneLocation $(deploymentRegion) + - avdSessionHostLocation $(deploymentRegion) + - fsLogixstorageSku 'Standard_LRS' + # - avdWrklSecretAccess $(avdWrklSecretAccess) + - existingVnetSubnetResourceId '/subscriptions/a165ed8a-0e83-46f1-9994-b216229c2da7/resourceGroups/azurelab-avd-networking/providers/Microsoft.Network/virtualNetworks/vnet-avd-canadacentral/subnets/subnet1' + - existingHubVnetResourceId '/subscriptions/4f6c98e1-04a4-49f0-abce-6240b1726c3f/resourceGroups/pubsec-hub-networking-rg/providers/Microsoft.Network/virtualNetworks/hub-vnet' + - useSharedImage $(useSharedImage) + - avdOsImage $(avdOsImage) + - createAvdVnet $(createAvdVnet) + - avdIdentityDomainName $(avdIdentityDomainName) + - avdDomainJoinUserName $(avdDomainJoinUserName) + - avdDomainJoinUserPassword $(avdDomainJoinUserPassword) + - avdVmLocalUserName $(avdVmLocalUserName) + - avdVmLocalUserPassword $(avdVmLocalUserPassword) + - avdDeployRAppGroup true + - avdDeploySessionHosts true + - avdStartVMOnConnect true + - createStartVmOnConnectCustomRole true + - vNetworkGatewayOnHub false + - createOUforStorage true + - storageOUName 'FsLogix User Profiles' diff --git a/.azuredevops/modulePipelines/ms.analysisservices.servers.yml b/.azuredevops/modulePipelines/ms.analysisservices.servers.yml new file mode 100644 index 000000000..625a1186c --- /dev/null +++ b/.azuredevops/modulePipelines/ms.analysisservices.servers.yml @@ -0,0 +1,52 @@ +name: 'AnalysisServices - Servers' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.analysisservices.servers.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.AnalysisServices/servers/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.AnalysisServices/servers' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.apimanagement.service.yml b/.azuredevops/modulePipelines/ms.apimanagement.service.yml new file mode 100644 index 000000000..43ae45a01 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.apimanagement.service.yml @@ -0,0 +1,52 @@ +name: 'ApiManagement - Service' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Soft-delete prevents re-deployment + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.apimanagement.service.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ApiManagement/service/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ApiManagement/service' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/max.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml b/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml new file mode 100644 index 000000000..7e045cf88 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml @@ -0,0 +1,62 @@ +name: 'Authorization - PolicyAssignments' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Authorization/policyAssignments/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Authorization/policyAssignments' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - 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 + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml b/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml new file mode 100644 index 000000000..41bfa990d --- /dev/null +++ b/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml @@ -0,0 +1,58 @@ +name: 'Authorization - PolicyDefinitions' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Authorization/policyDefinitions/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Authorization/policyDefinitions' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - 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 + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml b/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml new file mode 100644 index 000000000..f43f19850 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml @@ -0,0 +1,62 @@ +name: 'Authorization - PolicyExemptions' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Authorization/policyExemptions/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Authorization/policyExemptions' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - 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 + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml b/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml new file mode 100644 index 000000000..56bade6ae --- /dev/null +++ b/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml @@ -0,0 +1,58 @@ +name: 'Authorization - PolicySetDefinitions' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Authorization/policySetDefinitions/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Authorization/policySetDefinitions' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - 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 + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml b/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml new file mode 100644 index 000000000..b4ad7d6ad --- /dev/null +++ b/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml @@ -0,0 +1,62 @@ +name: 'Authorization - RoleAssignments' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Authorization/roleAssignments/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Authorization/roleAssignments' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - 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 + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml b/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml new file mode 100644 index 000000000..044f4f0ad --- /dev/null +++ b/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml @@ -0,0 +1,62 @@ +name: 'Authorization - RoleDefinitions' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Authorization/roleDefinitions/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Authorization/roleDefinitions' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - 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 + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.automation.automationaccounts.yml b/.azuredevops/modulePipelines/ms.automation.automationaccounts.yml new file mode 100644 index 000000000..b379d53d3 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.automation.automationaccounts.yml @@ -0,0 +1,52 @@ +name: 'Automation - AutomationAccounts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.automation.automationaccounts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Automation/automationAccounts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Automation/automationAccounts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.batch.batchaccounts.yml b/.azuredevops/modulePipelines/ms.batch.batchaccounts.yml new file mode 100644 index 000000000..7c10f8bad --- /dev/null +++ b/.azuredevops/modulePipelines/ms.batch.batchaccounts.yml @@ -0,0 +1,51 @@ +name: 'Batch - BatchAccounts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.batch.batchaccounts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Batch/batchAccounts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Batch/batchAccounts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml b/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml new file mode 100644 index 000000000..b95d423f8 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml @@ -0,0 +1,51 @@ +name: 'CognitiveServices - Accounts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Soft-delete prevents re-deployment + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.CognitiveServices/accounts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.CognitiveServices/accounts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.availabilitysets.yml b/.azuredevops/modulePipelines/ms.compute.availabilitysets.yml new file mode 100644 index 000000000..13f0d8bfb --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.availabilitysets.yml @@ -0,0 +1,51 @@ +name: 'Compute - AvailabilitySets' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.availabilitysets.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/availabilitySets/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/availabilitySets' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.diskencryptionsets.yml b/.azuredevops/modulePipelines/ms.compute.diskencryptionsets.yml new file mode 100644 index 000000000..ab1a408aa --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.diskencryptionsets.yml @@ -0,0 +1,51 @@ +name: 'Compute - DiskEncryptionSets' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.diskencryptionsets.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/diskEncryptionSets/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/diskEncryptionSets' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.disks.yml b/.azuredevops/modulePipelines/ms.compute.disks.yml new file mode 100644 index 000000000..d63fbedbe --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.disks.yml @@ -0,0 +1,54 @@ +name: 'Compute - Disks' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.disks.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/disks/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/disks' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/image.parameters.json + - path: $(modulePath)/.parameters/import.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.galleries.yml b/.azuredevops/modulePipelines/ms.compute.galleries.yml new file mode 100644 index 000000000..df5e4455b --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.galleries.yml @@ -0,0 +1,56 @@ +name: 'Compute - Galleries' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.galleries.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/galleries/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/galleries' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + parameters: + deploymentBlocks: + - path: $(modulePath)/.parameters/images.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/images.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.images.yml b/.azuredevops/modulePipelines/ms.compute.images.yml new file mode 100644 index 000000000..fcd28cee5 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.images.yml @@ -0,0 +1,51 @@ +name: 'Compute - Images' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.images.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/images/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/images' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.proximityplacementgroups.yml b/.azuredevops/modulePipelines/ms.compute.proximityplacementgroups.yml new file mode 100644 index 000000000..21ce3f518 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.proximityplacementgroups.yml @@ -0,0 +1,51 @@ +name: 'Compute - ProximityPlacementGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.proximityplacementgroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/proximityPlacementGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/proximityPlacementGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.virtualmachines.yml b/.azuredevops/modulePipelines/ms.compute.virtualmachines.yml new file mode 100644 index 000000000..ec6e767fa --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.virtualmachines.yml @@ -0,0 +1,54 @@ +name: 'Compute - VirtualMachines' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.virtualmachines.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/virtualMachines/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/virtualMachines' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/linux.min.parameters.json + - path: $(modulePath)/.parameters/linux.parameters.json + - path: $(modulePath)/.parameters/windows.min.parameters.json + - path: $(modulePath)/.parameters/windows.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.compute.virtualmachinescalesets.yml b/.azuredevops/modulePipelines/ms.compute.virtualmachinescalesets.yml new file mode 100644 index 000000000..b8b9df5d9 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.compute.virtualmachinescalesets.yml @@ -0,0 +1,54 @@ +name: 'Compute - VirtualMachineScaleSets' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.compute.virtualmachinescalesets.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Compute/virtualMachineScaleSets/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Compute/virtualMachineScaleSets' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/linux.min.parameters.json + - path: $(modulePath)/.parameters/linux.parameters.json + - path: $(modulePath)/.parameters/windows.min.parameters.json + - path: $(modulePath)/.parameters/windows.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.consumption.budgets.yml b/.azuredevops/modulePipelines/ms.consumption.budgets.yml new file mode 100644 index 000000000..2889da608 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.consumption.budgets.yml @@ -0,0 +1,51 @@ +name: 'Consumption - Budgets' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.consumption.budgets.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Consumption/budgets/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Consumption/budgets' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.containerinstance.containergroups.yml b/.azuredevops/modulePipelines/ms.containerinstance.containergroups.yml new file mode 100644 index 000000000..97c564067 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.containerinstance.containergroups.yml @@ -0,0 +1,51 @@ +name: 'ContainerInstance - ContainerGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.containerinstance.containergroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ContainerInstance/containerGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ContainerInstance/containerGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.containerregistry.registries.yml b/.azuredevops/modulePipelines/ms.containerregistry.registries.yml new file mode 100644 index 000000000..c42b35b3e --- /dev/null +++ b/.azuredevops/modulePipelines/ms.containerregistry.registries.yml @@ -0,0 +1,52 @@ +name: 'ContainerRegistry - Registries' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.containerregistry.registries.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ContainerRegistry/registries/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ContainerRegistry/registries' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.containerservice.managedclusters.yml b/.azuredevops/modulePipelines/ms.containerservice.managedclusters.yml new file mode 100644 index 000000000..9b4f47bf4 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.containerservice.managedclusters.yml @@ -0,0 +1,52 @@ +name: 'ContainerService - ManagedClusters' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.containerservice.managedclusters.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ContainerService/managedClusters/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ContainerService/managedClusters' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/azure.parameters.json + - path: $(modulePath)/.parameters/kubenet.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.databricks.workspaces.yml b/.azuredevops/modulePipelines/ms.databricks.workspaces.yml new file mode 100644 index 000000000..bca028670 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.databricks.workspaces.yml @@ -0,0 +1,51 @@ +name: 'Databricks - Workspaces' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.databricks.workspaces.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Databricks/workspaces/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Databricks/workspaces' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.datafactory.factories.yml b/.azuredevops/modulePipelines/ms.datafactory.factories.yml new file mode 100644 index 000000000..e54b36af1 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.datafactory.factories.yml @@ -0,0 +1,51 @@ +name: 'DataFactory - Factories' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.datafactory.factories.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.DataFactory/factories/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.DataFactory/factories' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.desktopvirtualization.applicationgroups.yml b/.azuredevops/modulePipelines/ms.desktopvirtualization.applicationgroups.yml new file mode 100644 index 000000000..16c658a13 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.desktopvirtualization.applicationgroups.yml @@ -0,0 +1,52 @@ +name: 'DesktopVirtualization - ApplicationGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.desktopvirtualization.applicationgroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.DesktopVirtualization/applicationgroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.DesktopVirtualization/applicationgroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.desktopvirtualization.hostpools.yml b/.azuredevops/modulePipelines/ms.desktopvirtualization.hostpools.yml new file mode 100644 index 000000000..ed7bb6b14 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.desktopvirtualization.hostpools.yml @@ -0,0 +1,51 @@ +name: 'DesktopVirtualization - HostPools' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.desktopvirtualization.hostpools.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.DesktopVirtualization/hostpools/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.DesktopVirtualization/hostpools' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.desktopvirtualization.workspaces.yml b/.azuredevops/modulePipelines/ms.desktopvirtualization.workspaces.yml new file mode 100644 index 000000000..d00f5b191 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.desktopvirtualization.workspaces.yml @@ -0,0 +1,51 @@ +name: 'DesktopVirtualization - Workspaces' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.desktopvirtualization.workspaces.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.DesktopVirtualization/workspaces/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.DesktopVirtualization/workspaces' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.documentdb.databaseaccounts.yml b/.azuredevops/modulePipelines/ms.documentdb.databaseaccounts.yml new file mode 100644 index 000000000..2203a61f3 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.documentdb.databaseaccounts.yml @@ -0,0 +1,53 @@ +name: 'DocumentDB - DatabaseAccounts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.documentdb.databaseaccounts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.DocumentDB/databaseAccounts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.DocumentDB/databaseAccounts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/mongodb.parameters.json + - path: $(modulePath)/.parameters/plain.parameters.json + - path: $(modulePath)/.parameters/sqldb.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml b/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml new file mode 100644 index 000000000..79d013839 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml @@ -0,0 +1,52 @@ +name: 'EventGrid - System Topics' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.EventGrid/systemTopics/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.EventGrid/systemTopics' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.eventgrid.topics.yml b/.azuredevops/modulePipelines/ms.eventgrid.topics.yml new file mode 100644 index 000000000..ba5ee65db --- /dev/null +++ b/.azuredevops/modulePipelines/ms.eventgrid.topics.yml @@ -0,0 +1,51 @@ +name: 'EventGrid - Topics' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.eventgrid.topics.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.EventGrid/topics/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.EventGrid/topics' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.eventhub.namespaces.yml b/.azuredevops/modulePipelines/ms.eventhub.namespaces.yml new file mode 100644 index 000000000..63b16c5b3 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.eventhub.namespaces.yml @@ -0,0 +1,52 @@ +name: 'EventHub - Namespaces' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.eventhub.namespaces.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.EventHub/namespaces/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.EventHub/namespaces' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.healthbot.healthbots.yml b/.azuredevops/modulePipelines/ms.healthbot.healthbots.yml new file mode 100644 index 000000000..0f8665822 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.healthbot.healthbots.yml @@ -0,0 +1,51 @@ +name: 'HealthBot - HealthBots' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.healthbot.healthbots.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.HealthBot/healthBots/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.HealthBot/healthBots' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.actiongroups.yml b/.azuredevops/modulePipelines/ms.insights.actiongroups.yml new file mode 100644 index 000000000..5afa006aa --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.actiongroups.yml @@ -0,0 +1,51 @@ +name: 'Insights - ActionGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.actiongroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/actionGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/actionGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.activitylogalerts.yml b/.azuredevops/modulePipelines/ms.insights.activitylogalerts.yml new file mode 100644 index 000000000..aaac601f7 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.activitylogalerts.yml @@ -0,0 +1,51 @@ +name: 'Insights - ActivityLogAlerts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.activitylogalerts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/activityLogAlerts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/activityLogAlerts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.components.yml b/.azuredevops/modulePipelines/ms.insights.components.yml new file mode 100644 index 000000000..b2ed16663 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.components.yml @@ -0,0 +1,51 @@ +name: 'Insights - Components' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.components.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/components/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/components' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.diagnosticsettings.yml b/.azuredevops/modulePipelines/ms.insights.diagnosticsettings.yml new file mode 100644 index 000000000..5a12f8475 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.diagnosticsettings.yml @@ -0,0 +1,51 @@ +name: 'Insights - DiagnosticSettings' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Needs custom removals script + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.diagnosticsettings.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/diagnosticSettings/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/diagnosticSettings' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.metricalerts.yml b/.azuredevops/modulePipelines/ms.insights.metricalerts.yml new file mode 100644 index 000000000..3042e4dab --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.metricalerts.yml @@ -0,0 +1,51 @@ +name: 'Insights - MetricAlerts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.metricalerts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/metricAlerts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/metricAlerts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.privatelinkscopes.yml b/.azuredevops/modulePipelines/ms.insights.privatelinkscopes.yml new file mode 100644 index 000000000..fd71a6746 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.privatelinkscopes.yml @@ -0,0 +1,51 @@ +name: 'Insights - PrivateLinkScopes' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.privatelinkscopes.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/privateLinkScopes/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/privateLinkScopes' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.insights.scheduledqueryrules.yml b/.azuredevops/modulePipelines/ms.insights.scheduledqueryrules.yml new file mode 100644 index 000000000..7e83d3b93 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.insights.scheduledqueryrules.yml @@ -0,0 +1,51 @@ +name: 'Insights - ScheduledQueryRules' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.insights.scheduledqueryrules.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Insights/scheduledQueryRules/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Insights/scheduledQueryRules' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.keyvault.vaults.yml b/.azuredevops/modulePipelines/ms.keyvault.vaults.yml new file mode 100644 index 000000000..5458a9b78 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.keyvault.vaults.yml @@ -0,0 +1,52 @@ +name: 'KeyVault - Vaults' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Soft-delete prevents re-deployment + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.keyvault.vaults.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.KeyVault/vaults/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.KeyVault/vaults' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.logic.workflows.yml b/.azuredevops/modulePipelines/ms.logic.workflows.yml new file mode 100644 index 000000000..0b8e56730 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.logic.workflows.yml @@ -0,0 +1,51 @@ +name: 'Logic - Workflows' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.logic.workflows.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Logic/workflows/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Logic/workflows' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.machinelearningservices.workspaces.yml b/.azuredevops/modulePipelines/ms.machinelearningservices.workspaces.yml new file mode 100644 index 000000000..c831fb4b7 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.machinelearningservices.workspaces.yml @@ -0,0 +1,51 @@ +name: 'MachineLearningServices - Workspaces' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.machinelearningservices.workspaces.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.MachineLearningServices/workspaces/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.MachineLearningServices/workspaces' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.managedidentity.userassignedidentities.yml b/.azuredevops/modulePipelines/ms.managedidentity.userassignedidentities.yml new file mode 100644 index 000000000..f20e2d034 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.managedidentity.userassignedidentities.yml @@ -0,0 +1,51 @@ +name: 'ManagedIdentity - UserAssignedIdentities' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.managedidentity.userassignedidentities.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ManagedIdentity/userAssignedIdentities/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ManagedIdentity/userAssignedIdentities' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.managedservices.registrationdefinitions.yml b/.azuredevops/modulePipelines/ms.managedservices.registrationdefinitions.yml new file mode 100644 index 000000000..76e583bd4 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.managedservices.registrationdefinitions.yml @@ -0,0 +1,52 @@ +name: 'ManagedServices - RegistrationDefinitions' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Needs a custom removal script + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.managedservices.registrationdefinitions.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ManagedServices/registrationDefinitions/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ManagedServices/registrationDefinitions' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + - path: $(modulePath)/.parameters/rg.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.management.managementgroups.yml b/.azuredevops/modulePipelines/ms.management.managementgroups.yml new file mode 100644 index 000000000..cc6f67fd1 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.management.managementgroups.yml @@ -0,0 +1,51 @@ +name: 'Management - ManagementGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.management.managementgroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Management/managementGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Management/managementGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.netapp.netappaccounts.yml b/.azuredevops/modulePipelines/ms.netapp.netappaccounts.yml new file mode 100644 index 000000000..c0beec10e --- /dev/null +++ b/.azuredevops/modulePipelines/ms.netapp.netappaccounts.yml @@ -0,0 +1,53 @@ +name: 'NetApp - NetAppAccounts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.netapp.netappaccounts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.NetApp/netAppAccounts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.NetApp/netAppAccounts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/nfs3.parameters.json + - path: $(modulePath)/.parameters/nfs41.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.applicationgateways.yml b/.azuredevops/modulePipelines/ms.network.applicationgateways.yml new file mode 100644 index 000000000..b680e5787 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.applicationgateways.yml @@ -0,0 +1,51 @@ +name: 'Network - ApplicationGateways' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.applicationgateways.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/applicationGateways/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/applicationGateways' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.applicationsecuritygroups.yml b/.azuredevops/modulePipelines/ms.network.applicationsecuritygroups.yml new file mode 100644 index 000000000..892d102c2 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.applicationsecuritygroups.yml @@ -0,0 +1,51 @@ +name: 'Network - ApplicationSecurityGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.applicationsecuritygroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/applicationSecurityGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/applicationSecurityGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.azurefirewalls.yml b/.azuredevops/modulePipelines/ms.network.azurefirewalls.yml new file mode 100644 index 000000000..42a913133 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.azurefirewalls.yml @@ -0,0 +1,51 @@ +name: 'Network - AzureFirewalls' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.azurefirewalls.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/azureFirewalls/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/azureFirewalls' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.bastionhosts.yml b/.azuredevops/modulePipelines/ms.network.bastionhosts.yml new file mode 100644 index 000000000..f94e4c933 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.bastionhosts.yml @@ -0,0 +1,52 @@ +name: 'Network - BastionHosts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.bastionhosts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/bastionHosts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/bastionHosts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.connections.yml b/.azuredevops/modulePipelines/ms.network.connections.yml new file mode 100644 index 000000000..43c0f01ec --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.connections.yml @@ -0,0 +1,51 @@ +name: 'Network - Connections' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.connections.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/connections/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/connections' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.ddosprotectionplans.yml b/.azuredevops/modulePipelines/ms.network.ddosprotectionplans.yml new file mode 100644 index 000000000..78e509684 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.ddosprotectionplans.yml @@ -0,0 +1,51 @@ +name: 'Network - DdosProtectionPlans' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.ddosprotectionplans.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/ddosProtectionPlans/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/ddosProtectionPlans' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.expressroutecircuits.yml b/.azuredevops/modulePipelines/ms.network.expressroutecircuits.yml new file mode 100644 index 000000000..d328763a7 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.expressroutecircuits.yml @@ -0,0 +1,51 @@ +name: 'Network - ExpressRouteCircuits' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.expressroutecircuits.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/expressRouteCircuits/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/expressRouteCircuits' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.firewallpolicies.yml b/.azuredevops/modulePipelines/ms.network.firewallpolicies.yml new file mode 100644 index 000000000..ba839cd41 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.firewallpolicies.yml @@ -0,0 +1,51 @@ +name: 'Network - Firewallpolicies' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.firewallpolicies.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/firewallpolicies/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/firewallpolicies' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.validate.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.ipgroups.yml b/.azuredevops/modulePipelines/ms.network.ipgroups.yml new file mode 100644 index 000000000..14c98650b --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.ipgroups.yml @@ -0,0 +1,51 @@ +name: 'Network - IpGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.ipgroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/ipGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/ipGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.loadbalancers.yml b/.azuredevops/modulePipelines/ms.network.loadbalancers.yml new file mode 100644 index 000000000..bc5150aee --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.loadbalancers.yml @@ -0,0 +1,52 @@ +name: 'Network - LoadBalancers' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.loadbalancers.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/loadBalancers/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/loadBalancers' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + - path: $(modulePath)/.parameters/min.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.localnetworkgateways.yml b/.azuredevops/modulePipelines/ms.network.localnetworkgateways.yml new file mode 100644 index 000000000..6325a2b08 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.localnetworkgateways.yml @@ -0,0 +1,51 @@ +name: 'Network - LocalNetworkGateways' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.localnetworkgateways.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/localNetworkGateways/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/localNetworkGateways' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.natgateways.yml b/.azuredevops/modulePipelines/ms.network.natgateways.yml new file mode 100644 index 000000000..0d8930a1a --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.natgateways.yml @@ -0,0 +1,51 @@ +name: 'Network - NatGateways' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.natgateways.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/natGateways/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/natGateways' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.networksecuritygroups.yml b/.azuredevops/modulePipelines/ms.network.networksecuritygroups.yml new file mode 100644 index 000000000..d2ee2f9cc --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.networksecuritygroups.yml @@ -0,0 +1,51 @@ +name: 'Network - NetworkSecurityGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.networksecuritygroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/networkSecurityGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/networkSecurityGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.networkwatchers.yml b/.azuredevops/modulePipelines/ms.network.networkwatchers.yml new file mode 100644 index 000000000..c9befd2ca --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.networkwatchers.yml @@ -0,0 +1,52 @@ +name: 'Network - NetworkWatchers' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Required as a dependency + Only one Network Watcher can exist in the same location. If removed, a default would be created in a dedicated RG + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.networkwatchers.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/networkWatchers/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/networkWatchers' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.privatednszones.yml b/.azuredevops/modulePipelines/ms.network.privatednszones.yml new file mode 100644 index 000000000..581625a02 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.privatednszones.yml @@ -0,0 +1,51 @@ +name: 'Network - PrivateDnsZones' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.privatednszones.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/privateDnsZones/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/privateDnsZones' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.privateendpoints.yml b/.azuredevops/modulePipelines/ms.network.privateendpoints.yml new file mode 100644 index 000000000..45b3b539a --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.privateendpoints.yml @@ -0,0 +1,52 @@ +name: 'Network - PrivateEndpoints' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.privateendpoints.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/privateEndpoints/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/privateEndpoints' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.publicipaddresses.yml b/.azuredevops/modulePipelines/ms.network.publicipaddresses.yml new file mode 100644 index 000000000..73bf881d1 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.publicipaddresses.yml @@ -0,0 +1,51 @@ +name: 'Network - PublicIpAddresses' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.publicipaddresses.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/publicIPAddresses/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/publicIPAddresses' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.publicipprefixes.yml b/.azuredevops/modulePipelines/ms.network.publicipprefixes.yml new file mode 100644 index 000000000..1be45a7d4 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.publicipprefixes.yml @@ -0,0 +1,51 @@ +name: 'Network - PublicIpPrefixes' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.publicipprefixes.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/publicIPPrefixes/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/publicIPPrefixes' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.routetables.yml b/.azuredevops/modulePipelines/ms.network.routetables.yml new file mode 100644 index 000000000..c3d0c05fb --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.routetables.yml @@ -0,0 +1,51 @@ +name: 'Network - RouteTables' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.routetables.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/routeTables/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/routeTables' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.trafficmanagerprofiles.yml b/.azuredevops/modulePipelines/ms.network.trafficmanagerprofiles.yml new file mode 100644 index 000000000..32059ca83 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.trafficmanagerprofiles.yml @@ -0,0 +1,51 @@ +name: 'Network - TrafficManagerProfiles' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.trafficmanagerprofiles.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/trafficmanagerprofiles/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/trafficmanagerprofiles' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.virtualhubs.yml b/.azuredevops/modulePipelines/ms.network.virtualhubs.yml new file mode 100644 index 000000000..ba7eb4d6b --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.virtualhubs.yml @@ -0,0 +1,52 @@ +name: 'Network: Virtual Hubs' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.virtualHubs.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/virtualHubs/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/virtualHubs' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.virtualnetworkgateways.yml b/.azuredevops/modulePipelines/ms.network.virtualnetworkgateways.yml new file mode 100644 index 000000000..c73ac8fa2 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.virtualnetworkgateways.yml @@ -0,0 +1,52 @@ +name: 'Network - VirtualNetworkGateways' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.virtualnetworkgateways.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/virtualNetworkGateways/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/virtualNetworkGateways' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/expressRoute.parameters.json + - path: $(modulePath)/.parameters/vpn.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.virtualnetworks.yml b/.azuredevops/modulePipelines/ms.network.virtualnetworks.yml new file mode 100644 index 000000000..cedac4fbb --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.virtualnetworks.yml @@ -0,0 +1,52 @@ +name: 'Network - VirtualNetworks' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.virtualnetworks.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/virtualNetworks/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/virtualNetworks' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + - path: $(modulePath)/.parameters/vnetPeering.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.network.virtualwans.yml b/.azuredevops/modulePipelines/ms.network.virtualwans.yml new file mode 100644 index 000000000..bef3372da --- /dev/null +++ b/.azuredevops/modulePipelines/ms.network.virtualwans.yml @@ -0,0 +1,51 @@ +name: 'Network - VirtualWans' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.network.virtualwans.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Network/virtualWans/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Network/virtualWans' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.operationalinsights.workspaces.yml b/.azuredevops/modulePipelines/ms.operationalinsights.workspaces.yml new file mode 100644 index 000000000..497dceb9f --- /dev/null +++ b/.azuredevops/modulePipelines/ms.operationalinsights.workspaces.yml @@ -0,0 +1,52 @@ +name: 'OperationalInsights - Workspaces' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.operationalinsights.workspaces.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.OperationalInsights/workspaces/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.OperationalInsights/workspaces' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.recoveryservices.vaults.yml b/.azuredevops/modulePipelines/ms.recoveryservices.vaults.yml new file mode 100644 index 000000000..77dae89ca --- /dev/null +++ b/.azuredevops/modulePipelines/ms.recoveryservices.vaults.yml @@ -0,0 +1,51 @@ +name: 'RecoveryServices - Vaults' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.recoveryservices.vaults.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.RecoveryServices/vaults/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.RecoveryServices/vaults' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.resources.deploymentscripts.yml b/.azuredevops/modulePipelines/ms.resources.deploymentscripts.yml new file mode 100644 index 000000000..b5e131051 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.resources.deploymentscripts.yml @@ -0,0 +1,51 @@ +name: 'Resources - DeploymentScripts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.resources.deploymentscripts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Resources/deploymentScripts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Resources/deploymentScripts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.resources.resourcegroups.yml b/.azuredevops/modulePipelines/ms.resources.resourcegroups.yml new file mode 100644 index 000000000..02638da8e --- /dev/null +++ b/.azuredevops/modulePipelines/ms.resources.resourcegroups.yml @@ -0,0 +1,51 @@ +name: 'Resources - ResourceGroups' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.resources.resourcegroups.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Resources/resourceGroups/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Resources/resourceGroups' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.resources.tags.yml b/.azuredevops/modulePipelines/ms.resources.tags.yml new file mode 100644 index 000000000..9b33b7cf8 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.resources.tags.yml @@ -0,0 +1,53 @@ +name: 'Resources - Tags' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.resources.tags.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Resources/tags/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Resources/tags' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/rg.parameters.json + - path: $(modulePath)/.parameters/sub.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.security.azuresecuritycenter.yml b/.azuredevops/modulePipelines/ms.security.azuresecuritycenter.yml new file mode 100644 index 000000000..f5e26899e --- /dev/null +++ b/.azuredevops/modulePipelines/ms.security.azuresecuritycenter.yml @@ -0,0 +1,51 @@ +name: 'Security - AzureSecurityCenter' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: false # Needs custom removals script + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.security.azuresecuritycenter.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Security/azureSecurityCenter/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Security/azureSecurityCenter' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.servicebus.namespaces.yml b/.azuredevops/modulePipelines/ms.servicebus.namespaces.yml new file mode 100644 index 000000000..b75325c71 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.servicebus.namespaces.yml @@ -0,0 +1,52 @@ +name: 'ServiceBus - Namespaces' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.servicebus.namespaces.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.ServiceBus/namespaces/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ServiceBus/namespaces' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.servicefabric.clusters.yml b/.azuredevops/modulePipelines/ms.servicefabric.clusters.yml new file mode 100644 index 000000000..de23be1ed --- /dev/null +++ b/.azuredevops/modulePipelines/ms.servicefabric.clusters.yml @@ -0,0 +1,53 @@ +name: 'Service Fabric - Clusters' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.servicefabric.clusters.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/Microsoft.ServiceFabric/clusters/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.ServiceFabric/clusters' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.validate.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/full.parameters.json + - path: $(modulePath)/.parameters/cert.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.sql.managedinstances.yml b/.azuredevops/modulePipelines/ms.sql.managedinstances.yml new file mode 100644 index 000000000..5734b967c --- /dev/null +++ b/.azuredevops/modulePipelines/ms.sql.managedinstances.yml @@ -0,0 +1,52 @@ +name: 'Sql - ManagedInstances' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.sql.managedinstances.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Sql/managedInstances/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Sql/managedInstances' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + defaultJobTimeoutInMinutes: 360 + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.sql.servers.yml b/.azuredevops/modulePipelines/ms.sql.servers.yml new file mode 100644 index 000000000..4a162b398 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.sql.servers.yml @@ -0,0 +1,51 @@ +name: 'Sql - Servers' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.sql.servers.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Sql/servers/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Sql/servers' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.storage.storageaccounts.yml b/.azuredevops/modulePipelines/ms.storage.storageaccounts.yml new file mode 100644 index 000000000..0dafd10e8 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.storage.storageaccounts.yml @@ -0,0 +1,53 @@ +name: 'Storage - StorageAccounts' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.storage.storageaccounts.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Storage/storageAccounts/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Storage/storageAccounts' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + - path: $(modulePath)/.parameters/v1.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.synapse.privatelinkhubs.yml b/.azuredevops/modulePipelines/ms.synapse.privatelinkhubs.yml new file mode 100644 index 000000000..81d79c3b0 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.synapse.privatelinkhubs.yml @@ -0,0 +1,52 @@ +name: 'Synapse - PrivateLinkHubs' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.synapse.privatelinkhubs.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Synapse/privateLinkHubs/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Synapse/privateLinkHubs' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.virtualmachineimages.imagetemplates.yml b/.azuredevops/modulePipelines/ms.virtualmachineimages.imagetemplates.yml new file mode 100644 index 000000000..99ce80ebb --- /dev/null +++ b/.azuredevops/modulePipelines/ms.virtualmachineimages.imagetemplates.yml @@ -0,0 +1,51 @@ +name: 'VirtualMachineImages - ImageTemplates' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.virtualmachineimages.imagetemplates.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.VirtualMachineImages/imageTemplates/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.VirtualMachineImages/imageTemplates' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.web.connections.yml b/.azuredevops/modulePipelines/ms.web.connections.yml new file mode 100644 index 000000000..b66056377 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.web.connections.yml @@ -0,0 +1,51 @@ +name: 'Web - Connections' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.web.connections.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Web/connections/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Web/connections' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.web.hostingenvironments.yml b/.azuredevops/modulePipelines/ms.web.hostingenvironments.yml new file mode 100644 index 000000000..3d51d4a23 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.web.hostingenvironments.yml @@ -0,0 +1,52 @@ +name: 'Web - HostingEnvironments' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.web.hostingenvironments.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Web/hostingEnvironments/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Web/hostingEnvironments' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + defaultJobTimeoutInMinutes: 180 + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.web.serverfarms.yml b/.azuredevops/modulePipelines/ms.web.serverfarms.yml new file mode 100644 index 000000000..970239004 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.web.serverfarms.yml @@ -0,0 +1,51 @@ +name: 'Web - Serverfarms' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.web.serverfarms.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Web/serverfarms/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Web/serverfarms' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/modulePipelines/ms.web.sites.yml b/.azuredevops/modulePipelines/ms.web.sites.yml new file mode 100644 index 000000000..32c7b7f9a --- /dev/null +++ b/.azuredevops/modulePipelines/ms.web.sites.yml @@ -0,0 +1,54 @@ +name: 'Web - Sites' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.web.sites.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.Web/sites/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.Web/sites' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/fa.min.parameters.json + - path: $(modulePath)/.parameters/fa.parameters.json + - path: $(modulePath)/.parameters/wa.min.parameters.json + - path: $(modulePath)/.parameters/wa.parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.azuredevops/pipelineTemplates/jobs.publishModule.yml b/.azuredevops/pipelineTemplates/jobs.publishModule.yml new file mode 100644 index 000000000..cb6298244 --- /dev/null +++ b/.azuredevops/pipelineTemplates/jobs.publishModule.yml @@ -0,0 +1,310 @@ +######################################################### +## PUBLISH PIPELINE ## +######################################################### +## +## This pipeline template contains the logic to publish module data as +## - A build artifact and/or +## - As a new version to a given storage account and/or +## - As a new version as an UniversalPackage to a given artifact-feed +## +######################################################### + +##---------------------------------------------## +## TEMPLATE PARAMETERS ## +##---------------------------------------------## +## +## By default it uses the variables specified in the below [parameters] section. However, you can overwrite these variables in the +## referencing pipeline by providing the parameter explicitly. +## +## NOTE: If you don't need to overwrite a shared value, you can IGNORE this section +## +## |======================================================================================================================================================================================================================| +## | Parameter | Default Value | Description | Example | +## |---------------------------------|--------------------------------------|---------------------------------------------------------------------------------------------------------|-----------------------------------| +## | displayName | 'Publish module' | Name for the pipeline job | 'Publish KeyVault' | +## | serviceConnection | '$(serviceConnection)' | The service connection that connects to Azure | 'demo-internal' | +## | poolName | '$(poolName)' | You can provide either a [poolname] or [vmImage] to run the job on | 'Custom Deployment Pool' | +## | vmImage | '$(vmImage)' | You can provide either a [poolname] or [vmImage] to run the job on | 'ubuntu20.04' | +## | defaultJobTimeoutInMinutes | 120 | The timeout for the job in this pipeline | 120 | +## | modulePath | '$(modulePath)' | The path to the module to deploy. E.g. [c:/KeyVault] | 'c:/KeyVault' | +## | templateSpecsRGName | '$(templateSpecsRGName)' | Required to publish to template spec. ResourceGroup of the template spec to publish to | 'mgmt-rg' | +## | templateSpecsRGLocation | '$(templateSpecsRGLocation)' | Required to publish to template spec. Location of the template spec resource group | 'West Europe' | +## | templateSpecsDescription | '$(templateSpecsDescription)' | Required to publish to template spec. Description of the template spec to publish to | 'IaCs module' | +## | vstsFeedToken | '$(vstsFeedToken)' | Required to publish to a DevOps feed. Token with access to the feed to publish to. | '...' | +## | vstsFeedName | '$(vstsFeedName)' | Required to publish to a DevOps feed. Name to the feed to publish to. | 'modules' | +## | vstsFeedProject | '$(vstsFeedProject)' | Required to publish to a DevOps feed. Name of the project hosting the artifacts feed. May be empty. | 'iacs' | +## | bicepRegistryName | '$(bicepRegistryName)' | Required to publish to the private bicep registry. Name of the hosting container registry | 'adpsxxazacrx001' | +## | bicepRegistryRGName | '$(bicepRegistryRGName)' | Required to publish to the private bicep registry. Resource group of the hosting container registry | 'artifacts-rg' | +## | bicepRegistryRgLocation | '$(bicepRegistryRgLocation)' | Required to publish to the private bicep registry. Location of the RG of the hosting container registry | 'West Europe' | +## | vstsOrganizationUri | '$(vstsOrganizationUri)' | Required to publish to a DevOps feed. Name of the organization hosting the artifacts feed. | 'servicescode' | +## | azurePowerShellVersion | '$(azurePowerShellVersion)' | Used for configuring the Azure PowerShell Version, one of the example values. | 'latestVersion' or 'OtherVersion' | +## | preferredAzurePowerShellVersion | '$(preferredAzurePowerShellVersion)' | Used for configuring the Azure PowerShell Version, either an empty string or specific version. | '4.4.0' | +## |======================================================================================================================================================================================================================| +## +##---------------------------------------------## + +parameters: + # Pipeline-related parameters + checkoutRepositories: '' + displayName: 'Publish module' + serviceConnection: '$(serviceConnection)' + poolName: '$(poolName)' + vmImage: '$(vmImage)' + defaultJobTimeoutInMinutes: 120 + modulesRepository: '$(modulesRepository)' + + # Logic-related parameters + ## Module-related + modulePath: '$(modulePath)' + + ## TemplateSpec-related + templateSpecsDoPublish: '$(templateSpecsDoPublish)' + templateSpecsRGName: '$(templateSpecsRGName)' + templateSpecsRGLocation: '$(templateSpecsRGLocation)' + templateSpecsDescription: '$(templateSpecsDescription)' + + ## Artifact-Feed-related + artifactsFeedDoPublish: '$(artifactsFeedDoPublish)' + vstsOrganizationUri: '$(vstsOrganizationUri)' + vstsFeedProject: '$(vstsFeedProject)' + vstsFeedName: '$(vstsFeedName)' + vstsFeedToken: '$(vstsFeedToken)' + + ## Private-Bicep-Registry-related + bicepRegistryDoPublish: '$(bicepRegistryDoPublish)' + bicepRegistryName: '$(bicepRegistryName)' + bicepRegistryRGName: '$(bicepRegistryRGName)' + bicepRegistryRgLocation: '$(bicepRegistryRgLocation)' + +##---------------------------------------------## +## TEMPLATE LOGIC ## +##---------------------------------------------## +jobs: + - job: + displayName: ${{ parameters.displayName }} + timeoutInMinutes: ${{ parameters.defaultJobTimeoutInMinutes }} + pool: + ${{ if ne(parameters.vmImage, '') }}: + vmImage: ${{ parameters.vmImage }} + ${{ if ne(parameters.poolName, '') }}: + name: ${{ parameters.poolName }} + steps: + # [Checkout Repositories] task(s) + #-------------------------------- + - checkout: self + - ${{ if ne(parameters.checkoutRepositories, '') }}: + - ${{ each checkoutRepository in parameters.checkoutRepositories }}: + - checkout: ${{ checkoutRepository }} + fetchDepth: 1 # the depth of commits to ask Git to fetch; if not set defaults to no limit + path: 's/${{ checkoutRepository }}' + + # [Agent] Prepare environment + #---------------------------- + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.Accounts' }, + @{ Name = 'Az.ContainerRegistry' }, + @{ Name = 'Az.Resources' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + + # [Multi Repo] Support task + #-------------------------- + - task: PowerShell@2 + displayName: Handle Multi-Repo Invocation + inputs: + targetType: inline + pwsh: true + script: | + # ---------------------------- # + # HANDLE MULTI-REPO INVOCATION # + # ---------------------------- # + + # Handle multiple-repositories + if( "${{ join(';',parameters.checkoutRepositories) }}".length -gt 0) { + Write-Verbose "Multi-Repo Checkout" -Verbose + $modulePath = Join-Path '$(System.DefaultWorkingDirectory)' '$(modulesRepository)' '${{ parameters.modulePath }}' + } else { + Write-Verbose "No Multi-Repo Checkout" -Verbose + $modulePath = Join-Path '$(System.DefaultWorkingDirectory)' '${{ parameters.modulePath }}' + } + Write-Output "##vso[task.setvariable variable=ENVMODULEPATH]$modulePath" + + # [Universal Artifact-feed publish] task(s) + #------------------------------------------ + - task: PowerShell@2 + displayName: 'Publish module to artifacts feed' + condition: and( + eq(variables['artifactsFeedDoPublish'], true), + succeeded() + ) + enabled: true + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' '$(pipelineFunctionsPath)' 'resourcePublish' 'Get-ModulesToPublish.ps1') + . (Join-Path '$(System.DefaultWorkingDirectory)' '$(pipelineFunctionsPath)' 'resourcePublish' 'Publish-ModuleToUniversalArtifactFeed.ps1') + + #Prioritizing the bicep file + $TemplateFilePath = Join-Path -Path '$(ENVMODULEPATH)' -ChildPath 'deploy.bicep' + if (-not (Test-Path $TemplateFilePath)) { + $TemplateFilePath = Join-Path -Path '$(ENVMODULEPATH)' -ChildPath 'deploy.json' + } + + $functionInput = @{ + TemplateFilePath = $TemplateFilePath + } + + Write-Verbose "Invoke Get-ModulesToPublish with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + # Get the modified child resources + $ModulesToPublish = Get-ModulesToPublish @functionInput -Verbose + + # Publish the modified child resources + foreach ($ModuleToPublish in $ModulesToPublish) { + $RelPath = (($ModuleToPublish.TemplateFilePath).Split('/arm/')[-1]).Split('/deploy.')[0] + Write-Host "##[group]$(' - [{0}] [{1}]' -f $RelPath, $ModuleToPublish.Version)" + + $functionInput = @{ + TemplateFilePath = $ModuleToPublish.TemplateFilePath + VstsOrganizationUri = '${{ parameters.vstsOrganizationUri }}' + VstsFeedProject = '${{ parameters.vstsFeedProject }}' + VstsFeedName = '${{ parameters.vstsFeedName }}' + ModuleVersion = $ModuleToPublish.Version + BearerToken = $env:TOKEN + } + + Write-Verbose "Invoke Publish-ModuleToUniversalArtifactFeed with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Publish-ModuleToUniversalArtifactFeed @functionInput -Verbose + Write-Host "##[endgroup]" + } + env: + TOKEN: $(vstsFeedToken) + + # [template-spec publish] task(s) + #-------------------------------- + - task: AzurePowerShell@5 + displayName: 'Publish module to template specs' + condition: and( + eq(variables['templateSpecsDoPublish'], true), + succeeded() + ) + enabled: true + inputs: + azureSubscription: '${{ parameters.serviceConnection }}' + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + pwsh: true + ScriptType: InlineScript + inline: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' '$(pipelineFunctionsPath)' 'resourcePublish' 'Get-ModulesToPublish.ps1') + . (Join-Path '$(System.DefaultWorkingDirectory)' '$(pipelineFunctionsPath)' 'resourcePublish' 'Publish-ModuleToTemplateSpec.ps1') + + #Prioritizing the bicep file + $TemplateFilePath = Join-Path -Path '$(ENVMODULEPATH)' -ChildPath 'deploy.bicep' + if (-not (Test-Path $TemplateFilePath)) { + $TemplateFilePath = Join-Path -Path '$(ENVMODULEPATH)' -ChildPath 'deploy.json' + } + + $functionInput = @{ + TemplateFilePath = $TemplateFilePath + } + + Write-Verbose "Invoke Get-ModulesToPublish with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + # Get the modified child resources + $ModulesToPublish = Get-ModulesToPublish @functionInput -Verbose + + # Publish the modified child resources + foreach ($ModuleToPublish in $ModulesToPublish) { + $RelPath = (($ModuleToPublish.TemplateFilePath).Split('/arm/')[-1]).Split('/deploy.')[0] + Write-Host "##[group]$(' - [{0}] [{1}]' -f $RelPath, $ModuleToPublish.Version)" + + $functionInput = @{ + TemplateFilePath = $ModuleToPublish.TemplateFilePath + TemplateSpecsRgName = '${{ parameters.templateSpecsRgName }}' + TemplateSpecsRgLocation = '${{ parameters.templateSpecsRgLocation }}' + TemplateSpecsDescription = '${{ parameters.templateSpecsDescription }}' + ModuleVersion = $ModuleToPublish.Version + } + + Write-Verbose "Invoke Publish-ModuleToTemplateSpec with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Publish-ModuleToTemplateSpec @functionInput -Verbose + Write-Host "##[endgroup]" + } + + # [private bicep registry publish] task(s) + #------------------------------------------- + - task: AzurePowerShell@5 + displayName: 'Publish module to private bicep registry' + condition: and( + eq(variables['bicepRegistryDoPublish'], true), + succeeded() + ) + enabled: true + inputs: + azureSubscription: '${{ parameters.serviceConnection }}' + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + pwsh: true + ScriptType: InlineScript + inline: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' '$(pipelineFunctionsPath)' 'resourcePublish' 'Get-ModulesToPublish.ps1') + . (Join-Path '$(System.DefaultWorkingDirectory)' '$(pipelineFunctionsPath)' 'resourcePublish' 'Publish-ModuleToPrivateBicepRegistry.ps1') + + #Prioritizing the bicep file + $TemplateFilePath = Join-Path -Path '$(ENVMODULEPATH)' -ChildPath 'deploy.bicep' + if (-not (Test-Path $TemplateFilePath)) { + $TemplateFilePath = Join-Path -Path '$(ENVMODULEPATH)' -ChildPath 'deploy.json' + } + + $functionInput = @{ + TemplateFilePath = $TemplateFilePath + } + + Write-Verbose "Invoke Get-ModulesToPublish with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + # Get the modified child resources + $ModulesToPublish = Get-ModulesToPublish @functionInput -Verbose + + # Publish the modified child resources + foreach ($ModuleToPublish in $ModulesToPublish) { + $RelPath = (($ModuleToPublish.TemplateFilePath).Split('/arm/')[-1]).Split('/deploy.')[0] + Write-Host "##[group]$(' - [{0}] [{1}]' -f $RelPath, $ModuleToPublish.Version)" + + $functionInput = @{ + TemplateFilePath = $ModuleToPublish.TemplateFilePath + BicepRegistryName = '${{ parameters.bicepRegistryName }}' + BicepRegistryRgName = '${{ parameters.bicepRegistryRgName }}' + BicepRegistryRgLocation = '${{ parameters.bicepRegistryRgLocation }}' + ModuleVersion = $ModuleToPublish.Version + } + + Write-Verbose "Invoke Publish-ModuleToPrivateBicepRegistry with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Publish-ModuleToPrivateBicepRegistry @functionInput -Verbose + Write-Host "##[endgroup]" + } diff --git a/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml b/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml new file mode 100644 index 000000000..0d263d687 --- /dev/null +++ b/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml @@ -0,0 +1,348 @@ +######################################################### +## DEPLOYMENT PIPELINE ## +######################################################### +## +## This pipeline template contains the logic to deploy a given module's ARM template using the provided parameter file(s) +## +## Enabled levels of deployment +## - Resource-Group-Level +## - Subscription-Level +## - Management-Group-Level +## - Tenant-Level +## +######################################################## +## +##---------------------------------------------## +## TEMPLATE PARAMETERS ## +##---------------------------------------------## +## +## By default it uses the variables specified in the below [parameters] section. However, you can overwrite these variables in the +## referencing pipeline by providing the parameter explicitly. +## +## NOTE: If you don't need to overwrite a shared value, you can IGNORE this section +## +## |=================================================================================================================================================================================================================================| +## | Parameter | Default Value | Description | Example | +## |---------------------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------|--------------------------------------------| +## | serviceConnection | '$(serviceConnection)' | The service connection that connects to Azure | 'demo-internal' | +## | removeDeployment | '$(removeDeployment)' | Set to [true] to flag resource for removal. If not provided, defaults to false. | 'true' | +## | poolName | '$(poolName)' | You can provide either a [poolname] or [vmImage] to run the job on | 'Custom Deployment Pool' | +## | vmImage | '$(vmImage)' | You can provide either a [poolname] or [vmImage] to run the job on | 'ubuntu20.04' | +## | defaultJobTimeoutInMinutes | 120 | The timeout for the job in this pipeline | 120 | +## | checkoutRepositories | '' | An optional list of repositories to check out at the beginning of this job in addition to the source | 'Components' | +## | modulePath | '$(modulePath)' | The path to the module to deploy. E.g. [c:/KeyVault] | 'c:/KeyVault' | +## | deploymentBlocks | | The parameter file(s) to deploy with. Must be provided | path: 'C:/parameters.json' | +## | location | '$(defaultLocation)' | The location to deploy with | 'EastUs2' | +## | resourceGroupName | '$(defaultResourceGroupName)' | The resourcegroup to deploy into. Required only for Resource-Group-Level deployments | 'validation-rg' | +## | subscriptionId | '$(ARM_SUBSCRIPTION_ID)' | The id of the subscription to deploy into when using a Management group service connection | 'aed7c000-6387-412e-bed0-24dfddf4bbc6' | +## | managementGroupId | '$(ARM_MGMTGROUP_ID)' | The id of the management group to deploy into. Required only for Management-Group-Level deployments | '6ycc9620-cb01-454f-9ebc-fc6b1df48d64' | +## | parametersRepository | '$(Build.Repository.Name)' | The respository with the parameter files. Defaults to the triggering repository | 'Solutions' | +## | modulesRepository | '$(modulesRepository)' | The respository with the modules. | 'Components' | +## | azurePowerShellVersion | '$(azurePowerShellVersion)' | Used for configuring the Azure PowerShellModules Version, one of the example values. | 'latestVersion' or 'OtherVersion' | +## | preferredAzurePowerShellVersion | '$(preferredAzurePowerShellVersion)' | Used for configuring the Azure PowerShellModules Version, either an empty string or the specific version. | '4.4.0' | +## |=================================================================================================================================================================================================================================| +## +##---------------------------------------------## + +parameters: + # Pipeline-related parameters + serviceConnection: '$(serviceConnection)' + poolName: '$(poolName)' + vmImage: '$(vmImage)' + defaultJobTimeoutInMinutes: 120 + checkoutRepositories: '' + dependsOn: [] + # Logic-related parameters + removeDeployment: false + modulePath: '$(modulePath)' + deploymentBlocks: '' + location: '$(defaultLocation)' + resourceGroupName: '$(defaultResourceGroupName)' + subscriptionId: '$(ARM_SUBSCRIPTION_ID)' + managementGroupId: '$(ARM_MGMTGROUP_ID)' + parametersRepository: '$(Build.Repository.Name)' + modulesRepository: '$(modulesRepository)' + # Azure PowerShell Version parameters + azurePowerShellVersion: '$(azurePowerShellVersion)' + preferredAzurePowerShellVersion: '$(preferredAzurePowerShellVersion)' + +##---------------------------------------------## +## TEMPLATE LOGIC ## +##---------------------------------------------## + +jobs: + - ${{ each deploymentBlock in parameters.deploymentBlocks }}: + - job: ${{ deploymentBlock.jobName }} + + ${{ if ne( deploymentBlock.displayName, '') }}: + displayName: ${{ deploymentBlock.displayName }} + ${{ if eq( deploymentBlock.displayName, '') }}: + displayName: Deploy with [${{ replace( deploymentBlock.path, '$(modulePath)', '') }}] + timeoutInMinutes: ${{ parameters.defaultJobTimeoutInMinutes }} + ${{ if ne( parameters.dependsOn, '') }}: + dependsOn: ${{ parameters.dependsOn }} + pool: + ${{ if ne(parameters.vmImage, '') }}: + vmImage: ${{ parameters.vmImage }} + ${{ if ne(parameters.poolName, '') }}: + name: ${{ parameters.poolName }} + + steps: + # [Checkout Repositories] task(s) + #-------------------------------- + - checkout: self + - ${{ if ne(parameters.checkoutRepositories, '') }}: + - ? ${{ each checkoutRepository in parameters.checkoutRepositories }} + : - checkout: ${{ checkoutRepository }} + fetchDepth: 1 # the depth of commits to ask Git to fetch; if not set defaults to no limit + path: 's/${{ checkoutRepository }}' + + # [Agent] Prepare environment + #---------------------------- + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.Accounts' }, + @{ Name = 'Az.Resources' } + ) + + # Additional PS modules need to be installed for the removal step in case it is enabled + if ('${{ parameters.removeDeployment}}' -eq 'true') { + $Modules += @( + @{ Name = 'Az.CognitiveServices' }, + @{ Name = 'Az.Compute' }, + @{ Name = 'Az.KeyVault' }, + @{ Name = 'Az.Monitor' }, + @{ Name = 'Az.OperationalInsights' }, + @{ Name = 'Az.RecoveryServices' } + ) + } + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + + # [Multi Repo] Support task + #-------------------------- + - task: PowerShell@2 + displayName: Handle Multi-Repo Invocation + inputs: + targetType: inline + pwsh: true + script: | + # Handle multiple-repositories + if( "${{ join(';',parameters.checkoutRepositories) }}".length -gt 0) { + Write-Verbose "Multi-Repo Checkout" -Verbose + $moduleRepoRoot = Join-Path '$(System.DefaultWorkingDirectory)' '$(modulesRepository)' + $parametersRepoRoot = Join-Path '$(System.DefaultWorkingDirectory)' '${{ parameters.parametersRepository }}' + } else { + Write-Verbose "No Multi-Repo Checkout" -Verbose + $moduleRepoRoot = '$(System.DefaultWorkingDirectory)' + $parametersRepoRoot = '$(System.DefaultWorkingDirectory)' + } + Write-Output "##vso[task.setvariable variable=ModuleRepoRoot]$moduleRepoRoot" + Write-Output "##vso[task.setvariable variable=parametersRepoRoot]$parametersRepoRoot" + + # [Agent] Replace tokens + #----------------------- + - task: AzurePowerShell@5 + displayName: 'Replace Tokens [${{ deploymentBlock.path }}] via connection [${{ parameters.serviceConnection }}]' + inputs: + azureSubscription: ${{ parameters.serviceConnection }} + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + ScriptType: InlineScript + pwsh: true + inline: | + # Load used functions + . (Join-Path '$(moduleRepoRoot)' 'utilities' 'pipelines' 'tokensReplacement' 'Convert-TokensInFile.ps1') + + # Load Settings File + $Settings = Get-Content -Path (Join-Path '$(moduleRepoRoot)' 'settings.json') | ConvertFrom-Json -AsHashTable + + # Construct Token Function Input + $ConvertTokensInputs = @{ + Tokens = @{} + FilePath = Join-Path '$(parametersRepoRoot)' '${{ deploymentBlock.path }}' + TokenPrefix = $Settings.parameterFileTokens.tokenPrefix + TokenSuffix = $Settings.parameterFileTokens.tokenSuffix + } + + # Add defaults + $ConvertTokensInputs.Tokens += @{ + resourceGroupName = '${{ parameters.resourceGroupName }}' + subscriptionId = '${{ parameters.subscriptionId }}' + managementGroupId = '${{ parameters.managementGroupId }}' + tenantId = '$(ARM_TENANT_ID)' + deploymentSpId = '$(DEPLOYMENT_SP_ID)' + } + + # Add local tokens + if ($Settings.parameterFileTokens.localTokens) { + $tokenMap = @{} + foreach ($token in $Settings.parameterFileTokens.localTokens) { + $tokenMap += @{ $token.name = $token.value } + } + Write-Verbose ('Using local tokens [{0}]' -f ($tokenMap.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens += $tokenMap + } + + # Add custom tokens (passed in via the pipeline) + if(-not [String]::IsNullOrEmpty('${{ deploymentBlock.customParameterFileTokens }}')) { + $customTokens = '${{ deploymentBlock.customParameterFileTokens }}' | ConvertFrom-Json -AsHashTable + Write-Verbose ('Using custom parameter file tokens [{0}]' -f ($customTokens.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens += $customTokens + } + + # Invoke Token Replacement Functionality + $null = Convert-TokensInFile @ConvertTokensInputs + + # [Validation] task(s) + #--------------------- + - task: AzurePowerShell@5 + displayName: 'Validate [${{ deploymentBlock.path }}] via connection [${{ parameters.serviceConnection }}]' + inputs: + azureSubscription: ${{ parameters.serviceConnection }} + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + ScriptType: InlineScript + pwsh: true + inline: | + # Load used functions + . (Join-Path '$(moduleRepoRoot)' '$(pipelineFunctionsPath)' 'resourceDeployment' 'Test-TemplateWithParameterFile.ps1') + + if(-not [String]::IsNullOrEmpty('${{ deploymentBlock.templateFilePath }}')) { + $templateFilePath = Join-Path '$(moduleRepoRoot)' '${{ deploymentBlock.templateFilePath }}' + } else { + # Use default path + $templateFilePath = (Test-Path (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.bicep')) ? + (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.bicep') : + (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.json') + } + + # ----------- # + # INVOKE TEST # + # ----------- # + $functionInput = @{ + templateFilePath = $templateFilePath + parameterFilePath = Join-Path '$(ParametersRepoRoot)' '${{ deploymentBlock.path }}' + location = '${{ parameters.location }}' + resourceGroupName = '${{ parameters.resourceGroupName }}' + subscriptionId = '${{ parameters.subscriptionId }}' + managementGroupId = '${{ parameters.managementGroupId }}' + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Test-TemplateWithParameterFile @functionInput -Verbose + + # [Deployment] task(s) + #--------------------- + - task: AzurePowerShell@5 + displayName: 'Deploy [${{ deploymentBlock.path }}] via connection [${{ parameters.serviceConnection }}]' + name: 'DeployModule' + inputs: + azureSubscription: ${{ parameters.serviceConnection }} + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + pwsh: true + ScriptType: InlineScript + inline: | + # Load used functions + . (Join-Path '$(moduleRepoRoot)' '$(pipelineFunctionsPath)' 'resourceDeployment' 'New-ModuleDeployment.ps1') + + if(-not [String]::IsNullOrEmpty('${{ deploymentBlock.templateFilePath }}')) { + $templateFilePath = Join-Path '$(moduleRepoRoot)' '${{ deploymentBlock.templateFilePath }}' + } else { + # Use default path + $templateFilePath = (Test-Path (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.bicep')) ? + (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.bicep') : + (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.json') + } + + # ----------------- # + # INVOKE DEPLOYMENT # + # ----------------- # + $functionInput = @{ + templateFilePath = $templateFilePath + parameterFilePath = Join-Path '$(parametersRepoRoot)' '${{ deploymentBlock.path }}' + location = '${{ parameters.location }}' + resourceGroupName = '${{ parameters.resourceGroupName }}' + subscriptionId = '${{ parameters.subscriptionId }}' + managementGroupId = '${{ parameters.managementGroupId }}' + doNotThrow = $true + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + # Invoke deployment + $res = New-ModuleDeployment @functionInput -Verbose + + # Get deployment name + Write-Host ('##vso[task.setvariable variable=deploymentName]{0}' -f $res.deploymentName) + + # Populate further outputs + $deploymentOutputHash=@{} + + foreach ($outputKey in $res.deploymentOutput.Keys) { + Write-Output ('##vso[task.setvariable variable={0}]{1}' -f $outputKey, $res.deploymentOutput[$outputKey].Value) + $deploymentOutputHash.add($outputKey,$res.deploymentOutput[$outputKey].Value) + } + + $deploymentOutput = $deploymentOutputHash | ConvertTo-Json -Compress -Depth 100 + Write-Verbose "Deployment output: $deploymentOutput" -Verbose + Write-Output ('##vso[task.setvariable variable={0};isOutput=true]{1}' -f 'deploymentOutput', $deploymentOutput) + + if ($res.ContainsKey('exception')) { + # Happens only if there is an exception + throw $res.exception + } + + # [Removal] task(s) + #------------------ + - task: AzurePowerShell@5 + displayName: 'Remove deployed resources via [${{ parameters.serviceConnection }}]' + condition: and(succeededOrFailed(), eq( '${{ parameters.removeDeployment }}', 'true'), not(eq(variables['deploymentName'],''))) + inputs: + azureSubscription: ${{ parameters.serviceConnection }} + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + ScriptType: InlineScript + failOnStandardError: false + pwsh: true + inline: | + # Load used function + . (Join-Path '$(moduleRepoRoot)' '$(pipelineFunctionsPath)' 'resourceRemoval' 'Initialize-DeploymentRemoval.ps1') + + if(-not [String]::IsNullOrEmpty('${{ deploymentBlock.templateFilePath }}')) { + $templateFilePath = Join-Path '$(moduleRepoRoot)' '${{ deploymentBlock.templateFilePath }}' + } else { + # Use default path + $templateFilePath = (Test-Path (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.bicep')) ? + (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.bicep') : + (Join-Path '$(ModuleRepoRoot)' '$(modulePath)' 'deploy.json') + } + + if (-not [String]::IsNullOrEmpty('$(deploymentName)')) { + $functionInput = @{ + DeploymentName = '$(deploymentName)' + TemplateFilePath = $templateFilePath + ResourceGroupName = '${{ parameters.resourceGroupName }}' + ManagementGroupId = '${{ parameters.managementGroupId }}' + Verbose = $true + } + + Write-Verbose 'Invoke task with' -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Initialize-DeploymentRemoval @functionInput + } diff --git a/.azuredevops/pipelineTemplates/jobs.validateModulePester.yml b/.azuredevops/pipelineTemplates/jobs.validateModulePester.yml new file mode 100644 index 000000000..f946e0ef4 --- /dev/null +++ b/.azuredevops/pipelineTemplates/jobs.validateModulePester.yml @@ -0,0 +1,283 @@ +######################################################### +## VALIDATION PIPELINE ## +######################################################### +## +## This pipeline template contains the logic to validate a given module's ARM template using the provided parameter file(s) +## +## Enabled levels of validation +## - Resource-Group-Level +## - Subscription-Level +## - Management-Group-Level +## - Tenant-Level +## +######################################################### +## +##---------------------------------------------## +## TEMPLATE PARAMETERS ## +##---------------------------------------------## +## +## By default it uses the variables specified in the below [parameters] section. However, you can overwrite these variables in the +## referencing pipeline by providing the parameter explicitly. +## +## NOTE: If you don't need to overwrite a shared value, you can IGNORE this section +## +## |=============================================================================================================================================================================================================================| +## | Parameter | Default Value | Description | Example | +## |---------------------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------|----------------------------------------| +## | serviceConnection | '$(serviceConnection)' | The service connection that connects to Azure | 'demo-internal' | +## | poolName | '$(poolName)' | You can provide either a [poolname] or [vmImage] to run the job on | 'Custom Deployment Pool' | +## | vmImage | '$(vmImage)' | You can provide either a [poolname] or [vmImage] to run the job on | 'ubuntu20.04' | +## | defaultJobTimeoutInMinutes | 120 | The timeout for the job in this pipeline | 120 | +## | checkoutRepositories | '' | An optional list of repositories to check out at the beginning of this job in addition to the source | 'Components' | +## | modulePath | '$(modulePath)' | The path to the module to deploy. E.g. [c:/KeyVault] | 'c:/KeyVault' | +## | location | '$(defaultLocation)' | The location to validate with | 'France Central' | +## | resourceGroupName | '$(defaultResourceGroupName)' | The resourcegroup to validate into. Required only for Resource-Group-Level validations | 'validation-rg' | +## | subscriptionId | '$(ARM_SUBSCRIPTION_ID)' | The id of the subscription to validate with when using a Management group service connection | 'aed7c000-6387-412e-bed0-24dfddf4bbc6' | +## | managementGroupId | '$(ARM_MGMTGROUP_ID)' | The id of the management group to validate with. Required only for Management-Group-Level validations | '477c9620-cb01-454f-9ebc-fc6b1df48c14' | +## | parametersRepository | '$(Build.Repository.Name)' | The respository with the parameter files. Defaults to the triggering repository | 'Solutions' | +## | modulesRepository | '$(modulesRepository)' | The respository with the modules. | 'Components' | +## | azurePowerShellVersion | '$(azurePowerShellVersion)' | Used for configuring the Azure PowerShellModules Version, one of the example values. | 'latestVersion' or 'OtherVersion' | +## | preferredAzurePowerShellVersion | '$(preferredAzurePowerShellVersion)' | Used for configuring the Azure PowerShellModules Version, either an empty string or the specific version. | '4.4.0' | +## |=============================================================================================================================================================================================================================| +## +##---------------------------------------------## + +parameters: + # Pipeline-related parameters + serviceConnection: '$(serviceConnection)' + poolName: '$(poolName)' + vmImage: '$(vmImage)' + defaultJobTimeoutInMinutes: 120 + checkoutRepositories: '' + # Logic-related parameters + modulePath: '$(modulePath)' + parametersRepository: '$(Build.Repository.Name)' + location: '$(defaultLocation)' + resourceGroupName: '$(defaultResourceGroupName)' + subscriptionId: '$(ARM_SUBSCRIPTION_ID)' + managementGroupId: '$(ARM_MGMTGROUP_ID)' + modulesRepository: '$(modulesRepository)' + # Azure PowerShell Version parameter + azurePowerShellVersion: '$(azurePowerShellVersion)' + preferredAzurePowerShellVersion: '$(preferredAzurePowerShellVersion)' + +##---------------------------------------------## +## TEMPLATE LOGIC ## +##---------------------------------------------## +jobs: + - job: + displayName: Run global tests + timeoutInMinutes: ${{ parameters.defaultJobTimeoutInMinutes }} + pool: + ${{ if ne(parameters.vmImage, '') }}: + vmImage: ${{ parameters.vmImage }} + ${{ if ne(parameters.poolName, '') }}: + name: ${{ parameters.poolName }} + steps: + # [Checkout Repositories] task(s) + #-------------------------------- + - checkout: self + - ${{ if ne(parameters.checkoutRepositories, '') }}: + - ${{ each checkoutRepository in parameters.checkoutRepositories }}: + - checkout: ${{ checkoutRepository }} + fetchDepth: 1 # the depth of commits to ask Git to fetch; if not set defaults to no limit + path: 's/${{ checkoutRepository }}' + + # [Multi Repo] Support task + #-------------------------- + - task: PowerShell@2 + displayName: Handle Multi-Repo Invocation + inputs: + targetType: inline + pwsh: true + script: | + # Handle multiple-repositories + if( "${{ join(';',parameters.checkoutRepositories) }}".length -gt 0) { + Write-Verbose "Multi-Repo Checkout" -Verbose + $moduleRepoRoot = Join-Path '$(System.DefaultWorkingDirectory)' '$(modulesRepository)' + $parametersRepoRoot = Join-Path '$(System.DefaultWorkingDirectory)' '${{ parameters.parametersRepository }}' + } else { + Write-Verbose "No Multi-Repo Checkout" -Verbose + $moduleRepoRoot = '$(System.DefaultWorkingDirectory)' + $parametersRepoRoot = '$(System.DefaultWorkingDirectory)' + } + Write-Output "##vso[task.setvariable variable=ModuleRepoRoot]$moduleRepoRoot" + Write-Output "##vso[task.setvariable variable=ParametersRepoRoot]$parametersRepoRoot" + + # [Agent] Prepare environment + #---------------------------- + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(moduleRepoRoot)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + # This is the latest tested Pester version. Uncomment the next line in case of a future breaking change in the default version installed on the runner. + # @{ Name = 'Pester'; Version = '5.3.1' } + @{ Name = 'Az.Resources' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + + # [Module Pester Test] task(s) + #----------------------------- + - task: AzurePowerShell@5 + displayName: 'Run general tests via (Pester) via connection [${{ parameters.serviceConnection }}]' + inputs: + azureSubscription: ${{ parameters.serviceConnection }} + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + ScriptType: InlineScript + pwsh: true + inline: | + $moduleFolderPaths = @(Join-Path '$(moduleRepoRoot)' '${{ parameters.modulePath }}') + $moduleFolderPaths += (Get-ChildItem $moduleFolderPaths -Recurse -Directory -Force).FullName | Where-Object { + (Get-ChildItem $_ -File -Depth 0 -Include @('deploy.json', 'deploy.bicep') -Force).Count -gt 0 + } + Write-Verbose "Execute tests in path(s):" -Verbose + foreach($moduleFolderPath in $moduleFolderPaths) { + Write-Verbose "- [($moduleFolderPath]" -Verbose + } + + Invoke-Pester -Configuration @{ + Run = @{ + Container = New-PesterContainer -Path (Join-Path '$(moduleRepoRoot)' 'arm' '.global' 'global.module.tests.ps1') -Data @{ + moduleFolderPaths = $moduleFolderPaths + } + } + Filter = @{ + ExcludeTag = 'ApiCheck' + } + TestResult = @{ + TestSuiteName = 'Global Module Tests' + OutputPath = 'arm/.global/global-testResults.xml' + OutputFormat = 'NUnitXml' + Enabled = $true + } + Output = @{ + Verbosity = 'Detailed' + } + } -ErrorAction 'Stop' + errorActionPreference: continue + + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testRunTitle: 'Global Module Tests' + testResultsFormat: NUnit + testResultsFiles: global-testResults.xml + failTaskOnFailedTests: true + searchFolder: 'arm/.global' + continueOnError: false + condition: succeededOrFailed() + + - job: + displayName: Run global API tests + timeoutInMinutes: ${{ parameters.defaultJobTimeoutInMinutes }} + pool: + ${{ if ne(parameters.vmImage, '') }}: + vmImage: ${{ parameters.vmImage }} + ${{ if ne(parameters.poolName, '') }}: + name: ${{ parameters.poolName }} + steps: + # [Checkout Repositories] task(s) + #-------------------------------- + - checkout: self + - ${{ if ne(parameters.checkoutRepositories, '') }}: + - ${{ each checkoutRepository in parameters.checkoutRepositories }}: + - checkout: ${{ checkoutRepository }} + fetchDepth: 1 # the depth of commits to ask Git to fetch; if not set defaults to no limit + path: 's/${{ checkoutRepository }}' + + # [Multi Repo] Support task + #-------------------------- + - task: PowerShell@2 + displayName: Handle Multi-Repo Invocation + inputs: + targetType: inline + pwsh: true + script: | + # Handle multiple-repositories + if( "${{ join(';',parameters.checkoutRepositories) }}".length -gt 0) { + Write-Verbose "Multi-Repo Checkout" -Verbose + $moduleRepoRoot = Join-Path '$(System.DefaultWorkingDirectory)' '$(modulesRepository)' + $parametersRepoRoot = Join-Path '$(System.DefaultWorkingDirectory)' '${{ parameters.parametersRepository }}' + } else { + Write-Verbose "No Multi-Repo Checkout" -Verbose + $moduleRepoRoot = '$(System.DefaultWorkingDirectory)' + $parametersRepoRoot = '$(System.DefaultWorkingDirectory)' + } + Write-Output "##vso[task.setvariable variable=ModuleRepoRoot]$moduleRepoRoot" + Write-Output "##vso[task.setvariable variable=ParametersRepoRoot]$parametersRepoRoot" + + # [Agent] Prepare environment + #---------------------------- + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(moduleRepoRoot)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Set agent up + Set-EnvironmentOnAgent + + # [Module Pester Test] task(s) + #----------------------------- + - task: AzurePowerShell@5 + displayName: 'Run API tests via (Pester) via connection [${{ parameters.serviceConnection }}]' + inputs: + azureSubscription: ${{ parameters.serviceConnection }} + azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }} + preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }} + ScriptType: InlineScript + pwsh: true + inline: | + $moduleFolderPaths = @(Join-Path '$(moduleRepoRoot)' '${{ parameters.modulePath }}') + $moduleFolderPaths += (Get-ChildItem $moduleFolderPaths -Recurse -Directory -Force).FullName | Where-Object { + (Get-ChildItem $_ -File -Depth 0 -Include @('deploy.json', 'deploy.bicep') -Force).Count -gt 0 + } + Write-Verbose "Execute tests in path(s):" -Verbose + foreach($moduleFolderPath in $moduleFolderPaths) { + Write-Verbose "- [($moduleFolderPath]" -Verbose + } + + Invoke-Pester -Configuration @{ + Run = @{ + Container = New-PesterContainer -Path (Join-Path '$(moduleRepoRoot)' 'arm' '.global' 'global.module.tests.ps1') -Data @{ + moduleFolderPaths = $moduleFolderPaths + } + } + Filter = @{ + Tag = 'ApiCheck' + } + TestResult = @{ + TestSuiteName = 'Global Module API Tests' + OutputPath = 'arm/.global/api-testResults.xml' + OutputFormat = 'NUnitXml' + Enabled = $true + } + Output = @{ + Verbosity = 'Detailed' + } + } -ErrorAction 'Stop' + errorActionPreference: continue + + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testRunTitle: 'Global Module API Tests' + testResultsFormat: NUnit + testResultsFiles: api-testResults.xml + failTaskOnFailedTests: true + searchFolder: 'arm/.global' + continueOnError: false + condition: succeededOrFailed() diff --git a/.azuredevops/pipelineVariables/global.variables.yml b/.azuredevops/pipelineVariables/global.variables.yml new file mode 100644 index 000000000..7e790694b --- /dev/null +++ b/.azuredevops/pipelineVariables/global.variables.yml @@ -0,0 +1,74 @@ +variables: + ###################################### + # Agent settings + ###################################### + + vmImage: 'ubuntu-latest' # Use this for Microsoft-hosted agents + poolName: '' # Use this for self-hosted agents + serviceConnection: 'CARML-CSU-Tenant-Connection' + + ###################################### + # Source + ###################################### + + vstsOrganization: servicescode + vstsOrganizationURI: '$(System.CollectionUri)' # The URI of the TFS collection or Azure DevOps organization. For example: https://dev.azure.com/fabrikam/. + vstsProject: '$(System.TeamProject)' + modulesRepository: ResourceModules # The repository hosting the deployment code (i.e. 'Components'). MUST be provided as a variable with every pipeline + modulePath: arm/$(moduleName) # only use in module pipelines + pipelineFunctionsPath: 'utilities/pipelines' + + ###################################### + # Validation deployment settings + ###################################### + + defaultLocation: 'West Europe' # The default location to test deploy resources to + defaultResourceGroupName: 'validation-rg' # The default resource group to test deployment resources into + + ###################################### + # Publish: Template-Spec settings + ###################################### + + templateSpecsDoPublish: true # Set to true, if you would like to publish module templates as template specs + templateSpecsRGName: 'artifacts-rg' # The name of the resource group to publish to. If the resource group does not exist, it will be created. + templateSpecsRGLocation: 'West Europe' # The location of the resource group to publish to + templateSpecsDescription: components # The description to add to template specs published by this platform + + ###################################### + # Publish: Universal packages settings + ###################################### + + artifactsFeedDoPublish: true # Set to true, if you would like to publish modules as Universal Packages (in Azure DevOps Artifacts) + vstsFeedName: 'ResourceModules' # The name of the Azure DevOps universal packages feed to publish to + vstsFeedProject: '$(System.TeamProject)' # The project that hosts the feed + vstsFeedToken: $(System.AccessToken) # The token used to publish universal packages into the feed above + + ###################################### + # Publish: Private Bicep Registry settings + ###################################### + + bicepRegistryDoPublish: true # Set to true, if you would like to publish module templates to a bicep registry + bicepRegistryName: adpsxxazacrx001 # The name of the bicep registry (ACR) to publish to. If it does not exist, it will be created. + bicepRegistryRGName: 'artifacts-rg' # The resource group that hosts the private bicep registry (ACR) + bicepRegistryRgLocation: 'West Europe' # The location of the resource group to publish to + + ###################################### + # Azure PowerShell Version + ###################################### + + # Should be set to 'latestVersion' unless there is an issue with the Az PowerShell modules. + # If a specific version needs to be set azurePowerShellVersion should be changed to 'OtherVersion'. + # NOTE: The strings are case sensitive and will not work unless properly entered. + azurePowerShellVersion: 'latestVersion' + # If using the latest version of the Az PowerShell modules, set `preferredAzurePowerShellVersion` to an empty string ''. + # If overriding the Az PowerShell module version, set to the version. Example: '4.4.0' + preferredAzurePowerShellVersion: '' +# +# NOTE: To override for just an individual template, just add the following to the +# templates pipeline.yml replacing '4.4.0' with the desired version: +# +# - name: azurePowerShellVersion +# value: 'OtherVersion' +# - name: preferredAzurePowerShellVersion +# value: '4.4.0' +# diff --git a/.azuredevops/platformPipelines/platform.dependencies.yml b/.azuredevops/platformPipelines/platform.dependencies.yml new file mode 100644 index 000000000..88bd93488 --- /dev/null +++ b/.azuredevops/platformPipelines/platform.dependencies.yml @@ -0,0 +1,886 @@ +name: '.Platform - Dependencies' + +parameters: + - name: deploySqlMiDependencies + displayName: Enable SqlMi dependencies deployment + type: boolean + default: false + - name: deployVhdDependencies + displayName: Enable deployment of a vhd stored in a blob container + type: boolean + default: false + +trigger: none + +# trigger: +# batch: true +# branches: +# include: +# - main +# paths: +# include: +# - '.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml' +# - '.azuredevops/platformPipelines/platform.dependencies.yml' +# - 'utilities/pipelines/dependencies/**' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: dependencyPath + value: 'utilities/pipelines/dependencies' + - name: modulesPath + value: 'arm' + - name: defaultResourceGroupName + value: 'validation-rg' + +stages: + - stage: deploy_rg + displayName: Deploy resource group + variables: + resourceType: 'Microsoft.Resources/resourceGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/validation.parameters.json + templateFilePath: $(templateFilePath) + displayName: Validation Resource Group + + - stage: deploy_msi + displayName: Deploy user assigned identity + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.ManagedIdentity/userAssignedIdentities' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: User Assigned Identity + jobName: job_deploy_msi + - job: job_set_msi_id + displayName: Set msi principal ID output + dependsOn: + - job_deploy_msi + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + variables: + deploymentOutput: $[ dependencies.job_deploy_msi.outputs['DeployModule.deploymentOutput'] ] + steps: + - task: PowerShell@2 + name: print_msi_prinId + inputs: + targetType: inline + pwsh: true + script: | + # Write-Verbose $(deploymentOutput) -Verbose + $msiPrincipalId = (ConvertFrom-Json '$(deploymentOutput)').principalId + Write-Verbose "msiPrincipalId: $msiPrincipalId" -Verbose + Write-Output ('##vso[task.setvariable variable={0};isOutput=true]{1}' -f 'msiPrincipalId', $msiPrincipalId) + + - stage: deploy_pa + displayName: Deploy policy assignment + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Authorization/policyAssignments' + templateFilePath: $(modulesPath)/$(resourceType)/subscription/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Policy assignment + + - stage: deploy_evh + displayName: Deploy event hub + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.EventHub/namespaces' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: EventHub + + - stage: deploy_law + displayName: Deploy log analytics workspace + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.OperationalInsights/workspaces' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default LAW + - path: $(dependencyPath)/$(resourceType)/parameters/aut.parameters.json + templateFilePath: $(templateFilePath) + displayName: Automation account LAW + - path: $(dependencyPath)/$(resourceType)/parameters/appi.parameters.json + templateFilePath: $(templateFilePath) + displayName: AppInsights LAW + + - stage: deploy_sa + displayName: Deploy storage account + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Storage/storageAccounts' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default storage account + jobName: default_sa + - path: $(dependencyPath)/$(resourceType)/parameters/law.parameters.json + templateFilePath: $(templateFilePath) + displayName: LAW storage account + - path: $(dependencyPath)/$(resourceType)/parameters/fa.parameters.json + templateFilePath: $(templateFilePath) + displayName: FunctionApp storage account + - job: + displayName: Upload files to storage account + dependsOn: + - default_sa + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.Storage' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Upload files to storage account + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'parameters.json' + # Load used functions + . (Join-Path '$(Build.SourcesDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Export-ContentToBlob.ps1') + . (Join-Path '$(Build.SourcesDirectory)' 'utilities' 'pipelines' 'tokensReplacement' 'Convert-TokensInFile.ps1') + + # Replace tokens in parameter file + $Settings = Get-Content -Path (Join-Path '$(Build.SourcesDirectory)' 'settings.json') | ConvertFrom-Json -AsHashTable + $ConvertTokensInputs = @{ + FilePath = $parameterFilePath + TokenPrefix = $Settings.parameterFileTokens.tokenPrefix + TokenSuffix = $Settings.parameterFileTokens.tokenSuffix + } + + # Add local tokens + if ($Settings.parameterFileTokens.localTokens) { + $tokenMap = @{} + foreach ($token in $Settings.parameterFileTokens.localTokens) { + $tokenMap += @{ $token.name = $token.value } + } + Write-Verbose ('Using local tokens [{0}]' -f ($tokenMap.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens = $tokenMap + } + + $null = Convert-TokensInFile @ConvertTokensInputs + + # Get storage account name + $storageAccountParameters = (ConvertFrom-Json (Get-Content -path $parameterFilePath -Raw)).parameters + + # Upload files to storage account + $functionInput = @{ + ResourceGroupName = '$(defaultResourceGroupName)' + StorageAccountName = $storageAccountParameters.name.value + contentDirectories = Join-Path '$(Build.SourcesDirectory)' $(dependencyPath) '$(resourceType)' 'uploads' + targetContainer = $storageAccountParameters.blobServices.value.containers[0].name + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Export-ContentToBlob @functionInput -Verbose + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - stage: deploy_sig + displayName: Deploy shared image gallery and definition + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Compute/galleries' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default SIG and SID + + - stage: deploy_imgt + displayName: Deploy image template + condition: and(succeeded(), eq('${{ parameters.deployVhdDependencies }}', true)) + dependsOn: + - deploy_rolea + - deploy_sig + - deploy_sa + variables: + resourceType: 'Microsoft.VirtualMachineImages\imageTemplates' + saResourceType: 'Microsoft.Storage\storageAccounts' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Image template + jobName: job_deploy_imgt + - job: + displayName: Trigger vhd build and store it to a storage account blob container + dependsOn: + - job_deploy_imgt + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + variables: + deploymentOutput: $[ dependencies.job_deploy_imgt.outputs['DeployModule.deploymentOutput'] ] + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.ImageBuilder' }, + @{ Name = 'Az.Storage' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Trigger building new image + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + # Retrieving parameters from previous job outputs + Write-Verbose "Retrieving parameters from previous job outputs" -Verbose + $imageTemplateName = (ConvertFrom-Json '$(deploymentOutput)').name + $imageTemplateResourceGroup = (ConvertFrom-Json '$(deploymentOutput)').resourceGroupName + + # Trigger new image creation + Write-Verbose "Trigger new image creation with imageTemplateName $imageTemplateName and imageTemplateResourceGroup $imageTemplateResourceGroup" -Verbose + Start-AzImageBuilderTemplate -ImageTemplateName $imageTemplateName -ResourceGroupName $imageTemplateResourceGroup + azurePowerShellVersion: 'LatestVersion' + pwsh: true + - task: AzurePowerShell@5 + displayName: Copy baked vhd to a storage account + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + + # Load used functions + . (Join-Path '$(Build.SourcesDirectory)' 'utilities' 'pipelines' 'tokensReplacement' 'Convert-TokensInFile.ps1') + + # Prepare replace tokens in parameter file + $Settings = Get-Content -Path (Join-Path '$(Build.SourcesDirectory)' 'settings.json') | ConvertFrom-Json -AsHashTable + $ConvertTokensInputs = @{ + TokenPrefix = $Settings.parameterFileTokens.tokenPrefix + TokenSuffix = $Settings.parameterFileTokens.tokenSuffix + } + if ($Settings.parameterFileTokens.localTokens) { + $tokenMap = @{} + foreach ($token in $Settings.parameterFileTokens.localTokens) { + $tokenMap += @{ $token.name = $token.value } + } + Write-Verbose ('Using local tokens [{0}]' -f ($tokenMap.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens = $tokenMap + } + + # Retrieving parameters from previous job outputs and parameter files + Write-Verbose "Retrieving parameters from previous job outputs" -Verbose + $imageTemplateName = (ConvertFrom-Json '$(deploymentOutput)').name + $imageTemplateResourceGroup = (ConvertFrom-Json '$(deploymentOutput)').resourceGroupName + + Write-Verbose "Retrieving parameters from storage account parameter files" -Verbose + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(saResourceType)' 'parameters' 'parameters.json' + $null = Convert-TokensInFile @ConvertTokensInputs -FilePath $parameterFilePath -Verbose + $storageAccountParameters = (ConvertFrom-Json (Get-Content -path $parameterFilePath -Raw)).parameters + + Write-Verbose "Retrieving parameters from image template parameter files" -Verbose + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'parameters.json' + $null = Convert-TokensInFile @ConvertTokensInputs -FilePath $parameterFilePath -Verbose + $imageTemplateParameters = (ConvertFrom-Json (Get-Content -path $parameterFilePath -Raw)).parameters + + # Initializing parameters before the blob copy + Write-Verbose "Initializing source storage account parameters before the blob copy" -Verbose + $imgtRunOutput = Get-AzImageBuilderRunOutput -ImageTemplateName $imageTemplateName -ResourceGroupName $imageTemplateResourceGroup | Where-Object ArtifactUri -NE $null + $sourceUri = $imgtRunOutput.ArtifactUri + $sourceStorageAccountName = $sourceUri.Split('//')[1].Split('.')[0] + $sourceStorageAccount = Get-AzStorageAccount | Where-Object StorageAccountName -EQ $sourceStorageAccountName + $sourceStorageAccountContext = $sourceStorageAccount.Context + $sourceStorageAccountRGName = $sourceStorageAccount.ResourceGroupName + Write-Verbose "Retrieving artifact uri $sourceUri stored in resource group $sourceStorageAccountRGName" -Verbose + + Write-Verbose "Initializing destination storage account parameters before the blob copy" -Verbose + $destinationStorageAccountName = $storageAccountParameters.name.value + $destinationStorageAccount = Get-AzStorageAccount | Where-Object StorageAccountName -EQ $destinationStorageAccountName + $destinationStorageAccountContext = $destinationStorageAccount.Context + $destinationContainerName = 'vhds' + $destinationBlobName = $imageTemplateParameters.name.value + $destinationBlobName = "$destinationBlobName.vhd" + Write-Verbose "Planning for destination blob name $destinationBlobName in container $destinationContainerName and storage account $destinationStorageAccountName" -Verbose + + # Copying the vhd to a destination blob container + Write-Verbose "Copying the vhd to a destination blob container" -Verbose + $resourceActionInputObject = @{ + AbsoluteUri = $sourceUri + Context = $sourceStorageAccountContext + DestContext = $destinationStorageAccountContext + DestBlob = $destinationBlobName + DestContainer = $destinationContainerName + Force = $true + } + Start-AzStorageBlobCopy @resourceActionInputObject + azPSVersion: 'latest' + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - stage: deploy_ag + displayName: Deploy action groups + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Insights/actionGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Action Group + + - stage: deploy_asg + displayName: Deploy application security groups + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Network/applicationSecurityGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Application Security Groups + + - stage: deploy_udr + displayName: Deploy route tables + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Network/routeTables' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default User Defined Routes + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/sqlMi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQLMI User Defined Routes + + - stage: deploy_nsg + displayName: Deploy network security groups + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Network/networkSecurityGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default NSG + - path: $(dependencyPath)/$(resourceType)/parameters/apgw.parameters.json + templateFilePath: $(templateFilePath) + displayName: App Gateway NSG + - path: $(dependencyPath)/$(resourceType)/parameters/ase.parameters.json + templateFilePath: $(templateFilePath) + displayName: ASE NSG + - path: $(dependencyPath)/$(resourceType)/parameters/bastion.parameters.json + templateFilePath: $(templateFilePath) + displayName: Bastion NSG + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/sqlmi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQLMI NSG + + - stage: deploy_pip + displayName: Deploy public IP addresses + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Network\publicIPAddresses' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/apgw.parameters.json + templateFilePath: $(templateFilePath) + displayName: App Gateway Public IP + - path: $(dependencyPath)/$(resourceType)/parameters/bas.parameters.json + templateFilePath: $(templateFilePath) + displayName: Bastion Public IP + - path: $(dependencyPath)/$(resourceType)/parameters/lb.parameters.json + templateFilePath: $(templateFilePath) + displayName: Load balancer Public IP + - path: $(dependencyPath)/$(resourceType)/parameters/lb.min.parameters.json + templateFilePath: $(templateFilePath) + displayName: Min Load balancer Public IP + - path: $(dependencyPath)/$(resourceType)/parameters/fw.parameters.json + templateFilePath: $(templateFilePath) + displayName: Firewall Public IP + + - stage: deploy_appi + displayName: Deploy application insight + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Insights/components' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Application Insights + + - stage: deploy_aut + displayName: Deploy automation account + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Automation/automationAccounts' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Automation Account + + - stage: deploy_avdhp + displayName: Deploy AVD host pool + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.DesktopVirtualization/hostpools' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default AVD Host Pool + + - stage: deploy_rsv + displayName: Deploy recovery services vault + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + - deploy_msi + variables: + resourceType: 'Microsoft.RecoveryServices/vaults' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + msiPrincipalId: $[ stageDependencies.deploy_msi.job_set_msi_id.outputs['print_msi_prinId.msiPrincipalId'] ] + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default recovery services vault + customParameterFileTokens: '{"msiPrincipalId":"$(msiPrincipalId)"}' + + - stage: deploy_kv + displayName: Deploy key vaults + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + - deploy_msi + variables: + resourceType: 'Microsoft.KeyVault/vaults' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + msiPrincipalId: $[ stageDependencies.deploy_msi.job_set_msi_id.outputs['print_msi_prinId.msiPrincipalId'] ] + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Key Vault + jobName: default_kv + customParameterFileTokens: '{"msiPrincipalId":"$(msiPrincipalId)"}' + - path: $(dependencyPath)/$(resourceType)/parameters/pe.parameters.json + templateFilePath: $(templateFilePath) + displayName: Private Endpoint Key Vault + customParameterFileTokens: '{"msiPrincipalId":"$(msiPrincipalId)"}' + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/sqlmi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQLMI key vault + jobName: sqlmi_kv + customParameterFileTokens: '{"msiPrincipalId":"$(msiPrincipalId)"}' + - job: + displayName: Set key vault secrets keys and certificates + dependsOn: + - default_kv + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.KeyVault' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Set key vault secrets keys and certificates + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'parameters.json' + # Load used functions + . (Join-Path '$(Build.SourcesDirectory)' 'utilities' 'pipelines' 'tokensReplacement' 'Convert-TokensInFile.ps1') + + # Replace tokens in parameter file + $Settings = Get-Content -Path (Join-Path '$(Build.SourcesDirectory)' 'settings.json') | ConvertFrom-Json -AsHashTable + $ConvertTokensInputs = @{ + FilePath = $parameterFilePath + TokenPrefix = $Settings.parameterFileTokens.tokenPrefix + TokenSuffix = $Settings.parameterFileTokens.tokenSuffix + } + if ($Settings.parameterFileTokens.localTokens) { + $tokenMap = @{} + foreach ($token in $Settings.parameterFileTokens.localTokens) { + $tokenMap += @{ $token.name = $token.value } + } + Write-Verbose ('Using local tokens [{0}]' -f ($tokenMap.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens = $tokenMap + } + $null = Convert-TokensInFile @ConvertTokensInputs + + # Get key vault name + $keyVaultParameters = (ConvertFrom-Json (Get-Content -Path $parameterFilePath -Raw)).parameters + $keyVaultName = $keyVaultParameters.name.value + + # Generate values + $usernameString = ( -join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | ForEach-Object { [char]$_ + "$_" })).substring(0, 19) # max length + $userName = ConvertTo-SecureString -String $usernameString -AsPlainText -Force + $passwordString = (New-Guid).Guid.SubString(0, 19) + $password = ConvertTo-SecureString -String $passwordString -AsPlainText -Force + $vpnSharedKeyString = (New-Guid).Guid.SubString(0, 32) + $vpnSharedKey = ConvertTo-SecureString -String $vpnSharedKeyString -AsPlainText -Force + + # Set secrets + # ------- + @( + @{ name = 'adminUsername'; secretValue = $username } # VirtualMachines and VMSS + @{ name = 'adminPassword'; secretValue = $password } # VirtualMachines and VMSS + @{ name = 'administratorLogin'; secretValue = $username } # Azure SQLServer + @{ name = 'administratorLoginPassword'; secretValue = $password } # Azure SQLServer + @{ name = 'vpnSharedKey'; secretValue = $vpnSharedKey } # VirtualNetworkGateway + @{ name = 'apimClientId'; secretValue = $username } # API management + @{ name = 'apimClientSecret'; secretValue = $password } # API management + ) | ForEach-Object { + $null = Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $_.name -SecretValue $_.secretValue + Write-Verbose ('Added secret [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Certificats + # ----------- + $certPolicy = New-AzKeyVaultCertificatePolicy -SecretContentType 'application/x-pkcs12' -SubjectName 'CN=fabrikam.com' -IssuerName 'Self' -ValidityInMonths 12 -ReuseKeyOnRenewal + @( + @{ name = 'applicationGatewaySslCertificate'; CertificatePolicy = $certPolicy } # ApplicationGateway + ) | ForEach-Object { + $null = Add-AzKeyVaultCertificate -VaultName $keyVaultName -Name $_.name -CertificatePolicy $_.CertificatePolicy + Write-Verbose ('Added certificate [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set keys + # ---- + @( + @{ name = 'keyEncryptionKey'; Destination = 'Software' } # DiskEncryptionSet, VirtualMachines and VMSS + ) | ForEach-Object { + $null = Add-AzKeyVaultKey -VaultName $keyVaultName -Name $_.name -Destination $_.Destination + Write-Verbose ('Added key [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - job: + displayName: Set sqlmi key vault secrets and keys + condition: eq(${{ parameters.deploySqlMiDependencies }}, true) + dependsOn: + - sqlmi_kv + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.KeyVault' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Set sqlmi key vault secrets and keys + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'sqlmi.parameters.json' + # Load used functions + . (Join-Path '$(Build.SourcesDirectory)' 'utilities' 'pipelines' 'tokensReplacement' 'Convert-TokensInFile.ps1') + + # Replace tokens in parameter file + $Settings = Get-Content -Path (Join-Path '$(Build.SourcesDirectory)' 'settings.json') | ConvertFrom-Json -AsHashTable + $ConvertTokensInputs = @{ + FilePath = $parameterFilePath + TokenPrefix = $Settings.parameterFileTokens.tokenPrefix + TokenSuffix = $Settings.parameterFileTokens.tokenSuffix + } + if ($Settings.parameterFileTokens.localTokens) { + $tokenMap = @{} + foreach ($token in $Settings.parameterFileTokens.localTokens) { + $tokenMap += @{ $token.name = $token.value } + } + Write-Verbose ('Using local tokens [{0}]' -f ($tokenMap.Keys -join ', ')) -Verbose + $ConvertTokensInputs.Tokens = $tokenMap + } + $null = Convert-TokensInFile @ConvertTokensInputs + + # Get key vault name + $keyVaultParameters = (ConvertFrom-Json (Get-Content -Path $parameterFilePath -Raw)).parameters + $keyVaultName = $keyVaultParameters.name.value + + # Generate values + $usernameString = ( -join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | ForEach-Object { [char]$_ + "$_" })).substring(0, 19) # max length + $userName = ConvertTo-SecureString -String $usernameString -AsPlainText -Force + $passwordString = (New-Guid).Guid.SubString(0, 19) + $password = ConvertTo-SecureString -String $passwordString -AsPlainText -Force + + # Set secrets + # ------- + @( + @{ name = 'administratorLogin'; secretValue = $username } # SQLManagedInstances + @{ name = 'administratorLoginPassword'; secretValue = $password } # SQLManagedInstances + ) | ForEach-Object { + $null = Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $_.name -SecretValue $_.secretValue + Write-Verbose ('Added secret [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set keys + # ---- + @( + @{ name = 'keyEncryptionKeySqlMi'; Destination = 'Software' } # SQLManagedInstances + ) | ForEach-Object { + $null = Add-AzKeyVaultKey -VaultName $keyVaultName -Name $_.name -Destination $_.Destination + Write-Verbose ('Added key [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - stage: deploy_avdag + displayName: Deploy AVD application group + dependsOn: + - deploy_avdhp + variables: + resourceType: 'Microsoft.DesktopVirtualization/applicationgroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Application Group + + - stage: deploy_rolea + displayName: Deploy role assignments + dependsOn: + - deploy_msi + variables: + resourceType: 'Microsoft.Authorization/roleAssignments' + 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 + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: MSI Role Assignment + customParameterFileTokens: '{"msiPrincipalId":"$(msiPrincipalId)"}' + + - stage: deploy_vnet + displayName: Deploy virtual networks + dependsOn: + - deploy_nsg + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - deploy_udr + variables: + resourceType: 'Microsoft.Network/virtualNetworks' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/1.bastion.parameters.json + templateFilePath: $(templateFilePath) + displayName: Bastion Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/2.vnetpeer01.parameters.json + templateFilePath: $(templateFilePath) + displayName: VNET PEering 1 Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/3.vnetpeer02.parameters.json + templateFilePath: $(templateFilePath) + displayName: VNET Peering 2 Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/4.azfw.parameters.json + templateFilePath: $(templateFilePath) + displayName: Azure Firewall Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/5.aks.parameters.json + templateFilePath: $(templateFilePath) + displayName: AKS Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/7.virtualHubConnection.parameters.json + templateFilePath: $(templateFilePath) + displayName: Virtual Hub Connection Virtual Network + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/6.sqlmi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQL MI Virtual Network + + - stage: deploy_dnszone + displayName: Deploy private DNS zones + dependsOn: + - deploy_vnet + variables: + resourceType: 'Microsoft.Network/privateDnsZones' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Private DNS Zones + + - stage: deploy_vm + displayName: Deploy virtual machines + dependsOn: + - deploy_vnet + - deploy_rsv + - deploy_kv + variables: + resourceType: 'Microsoft.Compute/virtualMachines' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Virtual Machine diff --git a/.azuredevops/platformPipelines/platform.updateReadMe.yml b/.azuredevops/platformPipelines/platform.updateReadMe.yml new file mode 100644 index 000000000..defe6e0d8 --- /dev/null +++ b/.azuredevops/platformPipelines/platform.updateReadMe.yml @@ -0,0 +1,88 @@ +name: '.Platform - Update ReadMe Module Tables' + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - 'arm/**/deploy.bicep' + - 'arm/**/deploy.json' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - name: pipelinePrincipalGitUserName + value: 'CARMLPipelinePrincipal' + - name: pipelinePrincipalGitUserEmail + value: 'CARML@noreply.github.com' + +jobs: + - job: Update_module_tables + pool: + ${{ if ne(variables.vmImage, '') }}: + vmImage: ${{ variables.vmImage }} + ${{ if ne(variables.poolName, '') }}: + name: ${{ variables.poolName }} + steps: + - checkout: self + persistCredentials: true + - task: PowerShell@2 + displayName: 'Update general ReadMe' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'tools' 'Set-ReadMeModuleTable.ps1') + + $functionInput = @{ + ModulesPath = Join-Path '$(System.DefaultWorkingDirectory)' 'arm' + FilePath = Join-Path '$(System.DefaultWorkingDirectory)' 'README.md' + Organization = '$(System.CollectionUri)'.Split('/')[3] + RepositoryName = '$(Build.Repository.Name)' + ColumnsInOrder = @('Name', 'Status') + SortByColumn = 'Name' + Environment = 'ADO' + ProjectName = '$(System.TeamProject)' + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Set-ReadMeModuleTable @functionInput -Verbose + - task: PowerShell@2 + displayName: 'Update module folder ReadMe' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'tools' 'Set-ReadMeModuleTable.ps1') + + $functionInput = @{ + ModulesPath = Join-Path '$(System.DefaultWorkingDirectory)' 'arm' + FilePath = Join-Path '$(System.DefaultWorkingDirectory)' 'arm/README.md' + Organization = '$(System.CollectionUri)'.Split('/')[3] + RepositoryName = '$(Build.Repository.Name)' + ColumnsInOrder = @('Name', 'ProviderNamespace','ResourceType') + Environment = 'ADO' + ProjectName = '$(System.TeamProject)' + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Set-ReadMeModuleTable @functionInput -Verbose + - task: PowerShell@2 + displayName: 'Push changes' + inputs: + targetType: inline + pwsh: true + script: | + git config --global user.email '$(pipelinePrincipalGitUserEmail)' + git config --global user.name '$(pipelinePrincipalGitUserName)' + Write-Verbose '$(Build.SourceBranch)' -Verbose + git add . + git commit -m "Push updated Readme file(s)" + git push $(Build.Repository.Uri) HEAD:$(Build.SourceBranch) diff --git a/.azuredevops/platformPipelines/platform.wiki-sync.yml b/.azuredevops/platformPipelines/platform.wiki-sync.yml new file mode 100644 index 000000000..67802a3ee --- /dev/null +++ b/.azuredevops/platformPipelines/platform.wiki-sync.yml @@ -0,0 +1,58 @@ +# NOTE: +# This pipeline requires a secret 'PLATFORM_REPO_UPDATE_PAT' set up in a library named 'PLATFORM_VARIABLES'. +# The secret's value should be a PAT token with the permissions to push to the repository's main branch. + +name: '.Platform - Sync Docs/Wiki' + +trigger: + branches: + include: + - main + paths: + include: + - 'docs/wiki/**' + +variables: + - group: 'PLATFORM_VARIABLES' + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - name: pipelinePrincipalGitUserName + value: 'CARMLPipelinePrincipal' + - name: pipelinePrincipalGitUserEmail + value: 'CARML@noreply.github.com' + +jobs: + - job: Update_module_tables + pool: + ${{ if ne('$(vmImage)', '') }}: + vmImage: '$(vmImage)' + ${{ if ne('$(poolName)', '') }}: + name: '$(poolName)' + steps: + - checkout: self + displayName: Checkout Source Repo + persistCredentials: true + # Create a variable + - task: PowerShell@2 + displayName: 'Checkout Wiki Repo' + inputs: + targetType: inline + pwsh: true + script: | + git config --global user.email '$(pipelinePrincipalGitUserEmail)' + git config --global user.name '$(pipelinePrincipalGitUserName)' + $repositoryEndpoint= 'https://' + '$(PLATFORM_REPO_UPDATE_PAT)' + '@github.com/' + '$(Build.Repository.Name)' + '.wiki' + git clone $repositoryEndpoint + - task: PowerShell@2 + displayName: 'Sync docs/wiki Into Wiki Repo' + inputs: + targetType: inline + pwsh: true + script: | + $docsPath = Join-Path '$(System.DefaultWorkingDirectory)' 'docs' 'wiki' + $wikiPath = ('$(Build.Repository.Name)').split('/')[1] + '.wiki' + $wikiRepository = Join-Path '$(System.DefaultWorkingDirectory)' $wikiPath + rsync -avzr --delete --exclude='.git/' $docsPath $wikiRepository + cd $wikiRepository + git add . + git commit -m "Push updated Wiki" + git push diff --git a/.github/workflows/compile-bicep-arm.yml b/.github/workflows/compile-bicep-arm.yml new file mode 100644 index 000000000..9e7b9d96d --- /dev/null +++ b/.github/workflows/compile-bicep-arm.yml @@ -0,0 +1,71 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the main branch + push: + branches: [ main ] + pull_request: + branches: [ main ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + # Runs ARM build from the bicep. Used for portal UI. Compile AVD baseline. + - name: bicep-build-output + uses: Azure/bicep-build-action@v1.0.0 + with: + bicepFilePath: ./workload/deploy-baseline.bicep + outputFilePath: ./workload/arm/deploy-baseline.json + + - name: Validate the AVD baseline output + shell: bash + run: | + FILE="./workload/arm/deploy-baseline.json" + if test -f "$FILE"; then + echo "$FILE created successfully" + else + echo "$FILE not found." + exit 1 + fi + + # Runs ARM build from the bicep. Used for portal UI. Compile AVD Custom image. + - name: bicep-build-output + uses: Azure/bicep-build-action@v1.0.0 + with: + bicepFilePath: ./workload/deploy-customImage.bicep + outputFilePath: ./workload/arm/deploy-customImage.json + + - name: Validate the AVD custom image output + shell: bash + run: | + FILE="./workload/arm/deploy-customImage.json" + if test -f "$FILE"; then + echo "$FILE created successfully" + else + echo "$FILE not found." + exit 1 + fi + + # Publish the compiled ARM templates to Github + - name: publish + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Automated update for ARM templates + + + diff --git a/.lycheeignore copy b/.lycheeignore copy new file mode 100644 index 000000000..cb8f72b8e --- /dev/null +++ b/.lycheeignore copy @@ -0,0 +1,9 @@ +https://foo.psd1/ +file:///github +https://mystorageaccount.blob.core.windows.net +https://mykeyvault.vault.azure.net +https://www.powershellgallery.com +https://github.com/myProject +http://validurltoconfiglocation/ +https://mycustomdependencylocation/ +http://tools.ietf.org/html/rfc6749#section-3.2 diff --git a/CARML README copy.md b/CARML README copy.md new file mode 100644 index 000000000..48d68ee2b --- /dev/null +++ b/CARML README copy.md @@ -0,0 +1,178 @@ +# ![AzureIcon] Common Azure Resource Modules Library + +## Description + +This repository includes a CI platform for and collection of mature and curated [Bicep][Bicep] modules. +The platform supports both ARM and Bicep and can be leveraged using GitHub actions as well as Azure DevOps pipelines. + +## Status + + + Super Linter + + + Issues + + + Pull requests + + +## Get started + +* For introduction guidance visit the [Wiki](https://github.com/azure/ResourceModules/wiki) +* For reference documentation visit [Enterprise-Scale](https://github.com/azure/enterprise-scale) +* For information on contributing, see [Contribution]() +* File an issue via [GitHub Issues](https://github.com/azure/ResourceModules/issues/new/choose) + +## Available Resource Modules + +| Name | Status | +| - | - | +| [Action Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/actionGroups) | [!['Insights: ActionGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.actiongroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.actiongroups.yml) | +| [Activity Log Alerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/activityLogAlerts) | [!['Insights: ActivityLogAlerts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.activitylogalerts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.activitylogalerts.yml) | +| [Activity Logs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/diagnosticSettings) | [!['Insights: DiagnosticSettings'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.diagnosticsettings.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.diagnosticsettings.yml) | +| [Analysis Services Server](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AnalysisServices/servers) | [!['AnalysisServices: Servers'](https://github.com/Azure/ResourceModules/actions/workflows/ms.analysisservices.servers.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.analysisservices.servers.yml) | +| [API Connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/connections) | [!['Web: Connections'](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.connections.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.connections.yml) | +| [API Management Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ApiManagement/service) | [!['ApiManagement: Service'](https://github.com/Azure/ResourceModules/actions/workflows/ms.apimanagement.service.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.apimanagement.service.yml) | +| [App Service Environments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/hostingEnvironments) | [!['Web: HostingEnvironments'](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.hostingenvironments.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.hostingenvironments.yml) | +| [App Service Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/serverfarms) | [!['Web: Serverfarms'](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.serverfarms.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.serverfarms.yml) | +| [Application Insights](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/components) | [!['Insights: Components'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.components.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.components.yml) | +| [Application Security Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationSecurityGroups) | [!['Network: ApplicationSecurityGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.applicationsecuritygroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.applicationsecuritygroups.yml) | +| [Automation Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Automation/automationAccounts) | [!['Automation: AutomationAccounts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.automation.automationaccounts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.automation.automationaccounts.yml) | +| [Availability Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/availabilitySets) | [!['Compute: AvailabilitySets'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.availabilitysets.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.availabilitysets.yml) | +| [AVD Application Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/applicationgroups) | [!['DesktopVirtualization: ApplicationGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.desktopvirtualization.applicationgroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.desktopvirtualization.applicationgroups.yml) | +| [AVD Host Pools](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/hostpools) | [!['DesktopVirtualization: HostPools'](https://github.com/Azure/ResourceModules/actions/workflows/ms.desktopvirtualization.hostpools.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.desktopvirtualization.hostpools.yml) | +| [AVD Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/workspaces) | [!['DesktopVirtualization: Workspaces'](https://github.com/Azure/ResourceModules/actions/workflows/ms.desktopvirtualization.workspaces.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.desktopvirtualization.workspaces.yml) | +| [Azure Compute Galleries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/galleries) | [!['Compute: Galleries'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.galleries.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.galleries.yml) | +| [Azure Databricks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Databricks/workspaces) | [!['Databricks: Workspaces'](https://github.com/Azure/ResourceModules/actions/workflows/ms.databricks.workspaces.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.databricks.workspaces.yml) | +| [Azure Firewalls](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/azureFirewalls) | [!['Network: AzureFirewalls'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.azurefirewalls.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.azurefirewalls.yml) | +| [Azure Health Bots](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.HealthBot/healthBots) | [!['HealthBot: HealthBots'](https://github.com/Azure/ResourceModules/actions/workflows/ms.healthbot.healthbots.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.healthbot.healthbots.yml) | +| [Azure Kubernetes Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerService/managedClusters) | [!['ContainerService: ManagedClusters'](https://github.com/Azure/ResourceModules/actions/workflows/ms.containerservice.managedclusters.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.containerservice.managedclusters.yml) | +| [Azure Monitor Private Link Scopes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/privateLinkScopes) | [!['Insights: PrivateLinkScopes'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.privatelinkscopes.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.privatelinkscopes.yml) | +| [Azure NetApp Files](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.NetApp/netAppAccounts) | [!['NetApp: NetAppAccounts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.netapp.netappaccounts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.netapp.netappaccounts.yml) | +| [Azure Security Center](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Security/azureSecurityCenter) | [!['Security: AzureSecurityCenter'](https://github.com/Azure/ResourceModules/actions/workflows/ms.security.azuresecuritycenter.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.security.azuresecuritycenter.yml) | +| [Bastion Hosts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/bastionHosts) | [!['Network: BastionHosts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.bastionhosts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.bastionhosts.yml) | +| [Batch Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Batch/batchAccounts) | [!['Batch: BatchAccounts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.batch.batchaccounts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.batch.batchaccounts.yml) | +| [Budgets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Consumption/budgets) | [!['Consumption: Budgets'](https://github.com/Azure/ResourceModules/actions/workflows/ms.consumption.budgets.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.consumption.budgets.yml) | +| [Cognitive Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.CognitiveServices/accounts) | [!['CognitiveServices: Accounts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.cognitiveservices.accounts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.cognitiveservices.accounts.yml) | +| [Compute Disks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/disks) | [!['Compute: Disks'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.disks.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.disks.yml) | +| [Container Instances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerInstance/containerGroups) | [!['ContainerInstance: ContainerGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.containerinstance.containergroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.containerinstance.containergroups.yml) | +| [Container Registries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerRegistry/registries) | [!['ContainerRegistry: Registries'](https://github.com/Azure/ResourceModules/actions/workflows/ms.containerregistry.registries.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.containerregistry.registries.yml) | +| [Data Factories](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DataFactory/factories) | [!['DataFactory: Factories'](https://github.com/Azure/ResourceModules/actions/workflows/ms.datafactory.factories.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.datafactory.factories.yml) | +| [DDoS Protection Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ddosProtectionPlans) | [!['Network: DdosProtectionPlans'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.ddosprotectionplans.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.ddosprotectionplans.yml) | +| [Deployment Scripts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/deploymentScripts) | [!['Resources: DeploymentScripts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.resources.deploymentscripts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.resources.deploymentscripts.yml) | +| [Disk Encryption Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/diskEncryptionSets) | [!['Compute: DiskEncryptionSets'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.diskencryptionsets.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.diskencryptionsets.yml) | +| [DocumentDB Database Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DocumentDB/databaseAccounts) | [!['DocumentDB: DatabaseAccounts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.documentdb.databaseaccounts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.documentdb.databaseaccounts.yml) | +| [Event Grid Topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/systemTopics) | [!['EventGrid: System Topics'](https://github.com/Azure/ResourceModules/actions/workflows/ms.eventgrid.systemtopics.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.eventgrid.systemtopics.yml) | +| [Event Grid Topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/topics) | [!['EventGrid: Topics'](https://github.com/Azure/ResourceModules/actions/workflows/ms.eventgrid.topics.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.eventgrid.topics.yml) | +| [Event Hub Namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventHub/namespaces) | [!['EventHub: Namespaces'](https://github.com/Azure/ResourceModules/actions/workflows/ms.eventhub.namespaces.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.eventhub.namespaces.yml) | +| [ExpressRoute Circuits](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/expressRouteCircuits) | [!['Network: ExpressRouteCircuits'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.expressroutecircuits.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.expressroutecircuits.yml) | +| [Image Templates](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.VirtualMachineImages/imageTemplates) | [!['VirtualMachineImages: ImageTemplates'](https://github.com/Azure/ResourceModules/actions/workflows/ms.virtualmachineimages.imagetemplates.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.virtualmachineimages.imagetemplates.yml) | +| [Images](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/images) | [!['Compute: Images'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.images.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.images.yml) | +| [IP Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ipGroups) | [!['Network: IpGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.ipgroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.ipgroups.yml) | +| [Key Vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KeyVault/vaults) | [!['KeyVault: Vaults'](https://github.com/Azure/ResourceModules/actions/workflows/ms.keyvault.vaults.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.keyvault.vaults.yml) | +| [Load Balancers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/loadBalancers) | [!['Network: LoadBalancers'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.loadbalancers.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.loadbalancers.yml) | +| [Local Network Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/localNetworkGateways) | [!['Network: LocalNetworkGateways'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.localnetworkgateways.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.localnetworkgateways.yml) | +| [Log Analytics Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.OperationalInsights/workspaces) | [!['OperationalInsights: Workspaces'](https://github.com/Azure/ResourceModules/actions/workflows/ms.operationalinsights.workspaces.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.operationalinsights.workspaces.yml) | +| [Logic Apps](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Logic/workflows) | [!['Logic: Workflows'](https://github.com/Azure/ResourceModules/actions/workflows/ms.logic.workflows.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.logic.workflows.yml) | +| [Machine Learning Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.MachineLearningServices/workspaces) | [!['MachineLearningServices: Workspaces'](https://github.com/Azure/ResourceModules/actions/workflows/ms.machinelearningservices.workspaces.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.machinelearningservices.workspaces.yml) | +| [Management Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Management/managementGroups) | [!['Management: ManagementGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.management.managementgroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.management.managementgroups.yml) | +| [Metric Alerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/metricAlerts) | [!['Insights: MetricAlerts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.metricalerts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.metricalerts.yml) | +| [NAT Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/natGateways) | [!['Network: NatGateways'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.natgateways.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.natgateways.yml) | +| [Network Application Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationGateways) | [!['Network: ApplicationGateways'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.applicationgateways.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.applicationgateways.yml) | +| [Network Firewall Policies](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/firewallPolicies) | [!['Network: FirewallPolicies'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.firewallpolicies.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.firewallpolicies.yml) | +| [Network Security Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkSecurityGroups) | [!['Network: NetworkSecurityGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.networksecuritygroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.networksecuritygroups.yml) | +| [Network Watchers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkWatchers) | [!['Network: NetworkWatchers'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.networkwatchers.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.networkwatchers.yml) | +| [Policy Assignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyAssignments) | [!['Authorization: PolicyAssignments'](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policyassignments.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policyassignments.yml) | +| [Policy Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyDefinitions) | [!['Authorization: PolicyDefinitions'](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policydefinitions.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policydefinitions.yml) | +| [Policy Exemptions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyExemptions) | [!['Authorization: PolicyExemptions'](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policyexemptions.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policyexemptions.yml) | +| [Policy Set Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policySetDefinitions) | [!['Authorization: PolicySetDefinitions'](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policysetdefinitions.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.policysetdefinitions.yml) | +| [Private DNS Zones](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateDnsZones) | [!['Network: PrivateDnsZones'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.privatednszones.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.privatednszones.yml) | +| [Private Endpoints](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateEndpoints) | [!['Network: PrivateEndpoints'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.privateendpoints.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.privateendpoints.yml) | +| [Proximity Placement Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/proximityPlacementGroups) | [!['Compute: ProximityPlacementGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.proximityplacementgroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.proximityplacementgroups.yml) | +| [Public IP Addresses](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPAddresses) | [!['Network: PublicIpAddresses'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.publicipaddresses.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.publicipaddresses.yml) | +| [Public IP Prefixes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPPrefixes) | [!['Network: PublicIpPrefixes'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.publicipprefixes.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.publicipprefixes.yml) | +| [Recovery Services Vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.RecoveryServices/vaults) | [!['RecoveryServices: Vaults'](https://github.com/Azure/ResourceModules/actions/workflows/ms.recoveryservices.vaults.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.recoveryservices.vaults.yml) | +| [Registration Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedServices/registrationDefinitions) | [!['ManagedServices: RegistrationDefinitions'](https://github.com/Azure/ResourceModules/actions/workflows/ms.managedservices.registrationdefinitions.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.managedservices.registrationdefinitions.yml) | +| [Resource Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/resourceGroups) | [!['Resources: ResourceGroups'](https://github.com/Azure/ResourceModules/actions/workflows/ms.resources.resourcegroups.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.resources.resourcegroups.yml) | +| [Resources Tags](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/tags) | [!['Resources: Tags'](https://github.com/Azure/ResourceModules/actions/workflows/ms.resources.tags.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.resources.tags.yml) | +| [Role Assignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleAssignments) | [!['Authorization: RoleAssignments'](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.roleassignments.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.roleassignments.yml) | +| [Role Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleDefinitions) | [!['Authorization: RoleDefinitions'](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.roledefinitions.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.authorization.roledefinitions.yml) | +| [Route Tables](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/routeTables) | [!['Network: RouteTables'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.routetables.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.routetables.yml) | +| [Scheduled Query Rules](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/scheduledQueryRules) | [!['Insights: ScheduledQueryRules'](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.scheduledqueryrules.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.insights.scheduledqueryrules.yml) | +| [Service Bus Namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceBus/namespaces) | [!['ServiceBus: Namespaces'](https://github.com/Azure/ResourceModules/actions/workflows/ms.servicebus.namespaces.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.servicebus.namespaces.yml) | +| [ServiceFabric Cluster](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceFabric/clusters) | [!['Service Fabric: Clusters'](https://github.com/Azure/ResourceModules/actions/workflows/ms.servicefabric.clusters.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.servicefabric.clusters.yml) | +| [SQL Managed Instances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/managedInstances) | [!['Sql: ManagedInstances'](https://github.com/Azure/ResourceModules/actions/workflows/ms.sql.managedinstances.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.sql.managedinstances.yml) | +| [SQL Servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/servers) | [!['Sql: Servers'](https://github.com/Azure/ResourceModules/actions/workflows/ms.sql.servers.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.sql.servers.yml) | +| [Storage Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Storage/storageAccounts) | [!['Storage: StorageAccounts'](https://github.com/Azure/ResourceModules/actions/workflows/ms.storage.storageaccounts.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.storage.storageaccounts.yml) | +| [Synapse PrivateLinkHubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Synapse/privateLinkHubs) | [!['Synapse: PrivateLinkHubs'](https://github.com/Azure/ResourceModules/actions/workflows/ms.synapse.privatelinkhubs.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.synapse.privatelinkhubs.yml) | +| [Traffic Manager Profiles](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/trafficmanagerprofiles) | [!['Network: TrafficManagerProfiles'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.trafficmanagerprofiles.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.trafficmanagerprofiles.yml) | +| [User Assigned Identities](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedIdentity/userAssignedIdentities) | [!['ManagedIdentity: UserAssignedIdentities'](https://github.com/Azure/ResourceModules/actions/workflows/ms.managedidentity.userassignedidentities.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.managedidentity.userassignedidentities.yml) | +| [Virtual Hub](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualHubs) | [!['Network: Virtual Hubs'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualhubs.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualhubs.yml) | +| [Virtual Machine Scale Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachineScaleSets) | [!['Compute: VirtualMachineScaleSets'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.virtualmachinescalesets.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.virtualmachinescalesets.yml) | +| [Virtual Machines](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachines) | [!['Compute: VirtualMachines'](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.virtualmachines.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.compute.virtualmachines.yml) | +| [Virtual Network Gateway Connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/connections) | [!['Network: Connections'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.connections.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.connections.yml) | +| [Virtual Network Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworkGateways) | [!['Network: VirtualNetworkGateways'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualnetworkgateways.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualnetworkgateways.yml) | +| [Virtual Networks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworks) | [!['Network: VirtualNetworks'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualnetworks.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualnetworks.yml) | +| [Virtual WANs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualWans) | [!['Network: VirtualWans'](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualwans.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.network.virtualwans.yml) | +| [Web/Function Apps](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/sites) | [!['Web: Sites'](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.sites.yml/badge.svg)](https://github.com/Azure/ResourceModules/actions/workflows/ms.web.sites.yml) | + +## Tooling + +| Name | Status | Docs | +| - | - | - | +| [ConvertTo-ARMTemplate](https://github.com/Azure/ResourceModules/blob/main/utilities/tools/ConvertTo-ARMTemplate.ps1) | [![.Platform: Test - ConvertTo-ARMTemplate.ps1](https://github.com/Azure/ResourceModules/actions/workflows/platform.convertToArmTemplate.tests.yml/badge.svg?branch=main)](https://github.com/Azure/ResourceModules/actions/workflows/platform.convertToArmTemplate.tests.yml) | [link](https://github.com/Azure/ResourceModules/wiki/UtilitiesConvertToARMTemplate) | + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit . + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## Trademarks + +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow +[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). +Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. +Any use of third-party trademarks or logos are subject to those third-party's policies. + +## Learn More + +* [PowerShell Documentation][PowerShellDocs] +* [Microsoft Azure Documentation][MicrosoftAzureDocs] +* [GitHubDocs][GitHubDocs] +* [Azure Resource Manager][AzureResourceManager] +* [Bicep][Bicep] + + + + +[Wiki]: +[ProjectSetup]: +[GitHubDocs]: +[AzureDevOpsDocs]: +[GitHubIssues]: +[Contributing]: CONTRIBUTING.md +[AzureIcon]: docs/media/MicrosoftAzure-32px.png +[PowershellIcon]: docs/media/MicrosoftPowerShellCore-32px.png +[BashIcon]: docs/media/Bash_Logo_black_and_white_icon_only-32px.svg.png + + +[Bicep]: +[Az]: +[AzGallery]: +[PowerShellCore]: +[InstallAzPs]: +[AzureResourceManager]: +[TemplateSpecs]: + +[ESLZ]: +[AzureSecurityBenchmark]: +[ESLZWorkloadTemplatesLibrary]: + + +[MicrosoftAzureDocs]: +[PowerShellDocs]: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..f9ba8cf65 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,9 @@ +# Microsoft Open Source Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +Resources: + +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..9a18be1d1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit . + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..9e841e7a2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/README.md b/README.md new file mode 100644 index 000000000..731c7be5d --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# Welcome to the Azure Virtual Desktop (AVD) Landing Zone Accelerator + +## Optional: Custom Image Build + +Deploy a custom image based on the latest version of the Azure marketplace image to an Azure Compute Gallery. The following images are offered: + - Windows 10 21H2 + - Windows 11 21H2 + - Windows 10 21H2 with O365 + - Windows 11 21H2 with O365 + + Custom image is optimized using [Virtual Desktop Optimization Tool (VDOT)](https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool) and patched with the latest Windows updates. + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Favdaccelerator%2Fmain%2Fworkload%2Farm%2Fdeploy-customImage.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Favdaccelerator%2Fmain%2Fworkload%2Fportal-ui%2Fportal-ui-customImage.json) + +## AVD Accelerator Baseline + +Deploy Azure Virtual Desktop (AVD) resources and dependent services for establishing the baseline +- AVD resources: workplace, two(2) application groups and host pool +- [Optional]: new virtual network (VNet) with baseline NSG and route table +- Azure Files Premium share. Integration with Active Directory +- Session Hosts + + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Favdaccelerator%2Fmain%2Fworkload%2Farm%2Fdeploy-baseline.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Favdaccelerator%2Fmain%2Fworkload%2Fportal-ui%2Fportal-ui-baseline.json) + +## Overview + +Enterprise-scale is an architectural approach and a reference implementation that enables effective construction and operation of landing zones on Azure, at scale. This approach aligns with the Azure roadmap and the Cloud Adoption Framework for Azure. + +AVD Landing Zone Accelerator represents the strategic design path and target technical state for AVD deployment. This solution provides an architectural approach and reference implementation to prepare landing zone subscriptions for a scalable AVD deployment. For the architectural guidance, check out [Enterprise-scale for AVD in Microsoft Docs](https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/enterprise-scale-landing-zone). + +The AVD Landing Zone Accelerator only addresses what gets deployed in the specific AVD landing zone subscriptions, highlighted by the red boxes in the picture above. It is assumed that an appropriate platform foundation is already setup which may or may not be the official [ALZ platform foundation](https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/implementation#reference-implementation). This means that policies and governance should already be in place or should be set up after this implementation and are not a part of the scope this program. The policies applied to management groups in the hierarchy above the subscription will trickle down to the Enterprise-scale for AVD landing zone subscriptions. + +## This Repository + +This repository will contain various customer scenarios that can help accelerate the development and deployment of AVD that conforms with [Enterprise-Scale for AVD best practices and guidelines](https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/ready). Each scenario aims to represent common customer experiences with the goal of accelerating the process of developing and deploying conforming AVD using IaaC. Each scenario will eventually have an ARM, Bicep, PowerShell and CLI version to choose from. +As of today, we have a first reference implementation scenario that is one of the most common ones used by Enterprise customers and partners and it can be used to deploy an AVD workload. We will continue to add new scenarios in future updates. + +## Next Steps + +Head over to [Getting Started Wiki](https://github.com/Azure/avdaccelerator/wiki/Getting-Started#Getting-Started) to review prerequisites and deployment options. + +## Baseline Architectural Diagram + +![AVD accelerator diagram](./workload/docs/diagrams/avd-accelerator-baseline.png) + +_Download a [Visio file](./workload/docs/diagrams/avd-accelerator-baseline-architecture.vsdx) of this architecture._ +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit [https://cla.opensource.microsoft.com](https://cla.opensource.microsoft.com). + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## Trademarks + +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft +trademarks or logos is subject to and must follow +[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/legal/intellectualproperty/trademarks). +Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. +Any use of third-party trademarks or logos are subject to those third-party's policies. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..4fa5946a8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 000000000..544b011a4 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,36 @@ +# Support + +## Microsoft Support Policy + +If issues are encountered when deploying these Bicep modules users will be able to engage Microsoft support via their usual channels. Please provide corelation IDs where possible when contacting support to be able to investigate the issue effectively and in a timely fashion. For instructions on how to get deployments and correlation ID, please follow this link [here](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/deployment-history?tabs=azure-portal#get-deployments-and-correlation-id). + +Following list of issues are within the scope of Microsoft support: + +- Underlying Resource or Resource Provider issues when deploying modules (e.g. Management Groups, Policies, Log Analytics Workspace, Virtual WAN, Virtual Network) for any deployment failure +- Module specific issues (e.g. template errors, internal server errors, etc.) +- Template specific issues (e.g. template publishing, resource removal, etc.) + +Any issues that are deemed outside of the above list by Microsoft support and/or requires bugfix in the module or code in the repo, Microsoft support will redirect user to file the issue on GitHub. + +Project maintainers and community aim to get issues resolved in timely fashion as per community support policy of this repo. + +## Community Support Policy + +Project maintainers will aim to respond to new issues on a best effort basis. + +## How to file issues and get help + +This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new Issue. + +For help and questions about using this project, please submit a Github issue with corresponding [Issue Labels found here](https://github.com/Azure/ResourceModules/labels). + + + +[ProjectSetup]: +[GitHubDocs]: +[AzureDevOpsDocs]: +[GitHubIssues]: +[Contributing]: CONTRIBUTING.md +[AzureIcon]: docs/media/MicrosoftAzure-32px.png +[PowershellIcon]: docs/media/MicrosoftPowerShellCore-32px.png +[BashIcon]: docs/media/Bash_Logo_black_and_white_icon_only-32px.svg.png diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..f53e97b6b --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,19 @@ +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +trigger: +- main + +pool: + vmImage: ubuntu-latest + +steps: +- script: echo Hello, world! + displayName: 'Run a one-line script' + +- script: | + echo Add other tasks to build, test, and deploy your project. + echo See https://aka.ms/yaml + displayName: 'Run a multi-line script' diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.AnalysisServices/servers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.AnalysisServices/servers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5187be04b --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource server 'Microsoft.AnalysisServices/servers@2017-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(server.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: server +}] diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.AnalysisServices/servers/.parameters/min.parameters.json new file mode 100644 index 000000000..33c06055d --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azasweumin001" + } + } +} diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/.parameters/parameters.json b/carml/1.0.0/Microsoft.AnalysisServices/servers/.parameters/parameters.json new file mode 100644 index 000000000..29ad01f8a --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azasweux001" + }, + "skuName": { + "value": "D1" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/deploy.bicep b/carml/1.0.0/Microsoft.AnalysisServices/servers/deploy.bicep new file mode 100644 index 000000000..a49d21a2f --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/deploy.bicep @@ -0,0 +1,152 @@ +@description('Required. The name of the Azure Analysis Services server to create.') +param name string + +@description('Optional. The sku name of the Azure Analysis Services server to create.') +param skuName string = 'S0' + +@description('Optional. The total number of query replica scale-out instances.') +param skuCapacity int = 1 + +@description('Optional. The inbound firewall rules to define on the server. If not specified, firewall is disabled.') +param firewallSettings object = { + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeStart: '0.0.0.0' + rangeEnd: '255.255.255.255' + } + ] + enablePowerBIService: true +} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Engine' + 'Service' +]) +param logsToEnable array = [ + 'Engine' + 'Service' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource server 'Microsoft.AnalysisServices/servers@2017-08-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + capacity: skuCapacity + } + properties: { + ipV4FirewallSettings: firewallSettings + } +} + +resource server_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${server.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: server +} + +resource server_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${server.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: server +} + +module server_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AnServicesServer-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: server.id + } +}] + +@description('The name of the analysis service') +output name string = server.name + +@description('The resource ID of the analysis service') +output resourceId string = server.id + +@description('The resource group the analysis service was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/readme.md b/carml/1.0.0/Microsoft.AnalysisServices/servers/readme.md new file mode 100644 index 000000000..524d12f5d --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/readme.md @@ -0,0 +1,93 @@ +# Analysis Services Server `[Microsoft.AnalysisServices/servers]` + +This module deploys an analysis service server. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AnalysisServices/servers` | 2017-08-01 | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.Network/VirtualNetwork` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `firewallSettings` | object | `{object}` | | Optional. The inbound firewall rules to define on the server. If not specified, firewall is disabled. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[Engine, Service]` | `[Engine, Service]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the Azure Analysis Services server to create. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuCapacity` | int | `1` | | Optional. The total number of query replica scale-out instances. | +| `skuName` | string | `S0` | | Optional. The sku name of the Azure Analysis Services server to create. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the analysis service | +| `resourceGroupName` | string | The resource group the analysis service was deployed into | +| `resourceId` | string | The resource ID of the analysis service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Servers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AnalysisServices/2017-08-01/servers) diff --git a/carml/1.0.0/Microsoft.AnalysisServices/servers/version.json b/carml/1.0.0/Microsoft.AnalysisServices/servers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.AnalysisServices/servers/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/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_authorizationServers.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_authorizationServers.bicep new file mode 100644 index 000000000..f8766ec1f --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_authorizationServers.bicep @@ -0,0 +1,109 @@ +@description('Required. Identifier of the authorization server.') +param name string + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. OAuth authorization endpoint. See .') +param authorizationEndpoint string + +@description('Optional. HTTP verbs supported by the authorization endpoint. GET must be always present. POST is optional. - HEAD, OPTIONS, TRACE, GET, POST, PUT, PATCH, DELETE') +param authorizationMethods array = [ + 'GET' +] + +@description('Optional. Specifies the mechanism by which access token is passed to the API. - authorizationHeader or query') +param bearerTokenSendingMethods array = [ + 'authorizationHeader' +] + +@description('Optional. Method of authentication supported by the token endpoint of this authorization server. Possible values are Basic and/or Body. When Body is specified, client credentials and other parameters are passed within the request body in the application/x-www-form-urlencoded format. - Basic or Body') +param clientAuthenticationMethod array = [ + 'Basic' +] + +@description('Optional. Optional reference to a page where client or app registration for this authorization server is performed. Contains absolute URL to entity being referenced.') +param clientRegistrationEndpoint string = '' + +@description('Required. Name of the key vault that stores clientId and clientSecret for this authorization server.') +param clientCredentialsKeyVaultId string + +@description('Required. Name of the secret that stores the Client or app ID registered with this authorization server.') +param clientIdSecretName string + +@description('Required. Name of the secret that stores the Client or app secret registered with this authorization server. This property will not be filled on \'GET\' operations! Use \'/listSecrets\' POST request to get the value.') +param clientSecretSecretName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Access token scope that is going to be requested by default. Can be overridden at the API level. Should be provided in the form of a string containing space-delimited values.') +param defaultScope string = '' + +@description('Optional. Description of the authorization server. Can contain HTML formatting tags.') +param serverDescription string = '' + +@description('Required. Form of an authorization grant, which the client uses to request the access token. - authorizationCode, implicit, resourceOwnerPassword, clientCredentials') +param grantTypes array + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner password.') +param resourceOwnerPassword string = '' + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner username.') +param resourceOwnerUsername string = '' + +@description('Optional. If true, authorization server will include state parameter from the authorization request to its response. Client may use state parameter to raise protocol security.') +param supportState bool = false + +@description('Optional. Additional parameters required by the token endpoint of this authorization server represented as an array of JSON objects with name and value string properties, i.e. {"name" : "name value", "value": "a value"}. - TokenBodyParameterContract object') +param tokenBodyParameters array = [] + +@description('Optional. OAuth token endpoint. Contains absolute URI to entity being referenced.') +param tokenEndpoint string = '' + +var defaultAuthorizationMethods = [ + 'GET' +] +var setAuthorizationMethods = union(authorizationMethods, defaultAuthorizationMethods) + +module pid_cuaId '../authorizationServers/.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' existing = { + name: last(split(clientCredentialsKeyVaultId, '/')) + scope: resourceGroup(split(clientCredentialsKeyVaultId, '/')[2], split(clientCredentialsKeyVaultId, '/')[4]) +} + +module authorizationServer '../authorizationServers/deploy.bicep' = { + name: '${deployment().name}-AuthorizationServer' + params: { + apiManagementServiceName: apiManagementServiceName + serverDescription: serverDescription + authorizationMethods: setAuthorizationMethods + clientAuthenticationMethod: clientAuthenticationMethod + tokenBodyParameters: tokenBodyParameters + tokenEndpoint: tokenEndpoint + supportState: supportState + defaultScope: defaultScope + bearerTokenSendingMethods: bearerTokenSendingMethods + resourceOwnerUsername: resourceOwnerUsername + resourceOwnerPassword: resourceOwnerPassword + name: name + clientRegistrationEndpoint: clientRegistrationEndpoint + authorizationEndpoint: authorizationEndpoint + grantTypes: grantTypes + clientId: keyVault.getSecret(clientIdSecretName) + clientSecret: keyVault.getSecret(clientSecretSecretName) + } +} + +@description('The name of the API management service authorization server') +output name string = authorizationServer.outputs.name + +@description('The resource ID of the API management service authorization server') +output resourceId string = authorizationServer.outputs.resourceId + +@description('The resource group the API management service authorization server was deployed into') +output resourceGroupName string = authorizationServer.outputs.resourceGroupName diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..2d8ca81f3 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'API Management Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c') + 'API Management Service Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61') + 'API Management Service Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource service 'Microsoft.ApiManagement/service@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(service.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: service +}] diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/.parameters/max.parameters.json b/carml/1.0.0/Microsoft.ApiManagement/service/.parameters/max.parameters.json new file mode 100644 index 000000000..127fda340 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/.parameters/max.parameters.json @@ -0,0 +1,177 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apim-max-001" + }, + "publisherEmail": { + "value": "apimgmt-noreply@mail.windowsazure.com" + }, + "publisherName": { + "value": "<>-az-amorg-x-001" + }, + "cuaId": { + "value": "00000-0-000000" + }, + "apis": { + "value": [ + { + "name": "echo-api", + "displayName": "Echo API", + "path": "echo", + "serviceUrl": "http://echoapi.cloudapp.net/api", + "apiVersionSet": { + "name": "echo-version-set", + "properties": { + "description": "echo-version-set", + "displayName": "echo-version-set", + "versioningScheme": "Segment" + } + } + } + ] + }, + "authorizationServers": { + "value": [ + { + "name": "AuthServer1", + "authorizationEndpoint": "https://login.microsoftonline.com/651b43ce-ccb8-4301-b551-b04dd872d401/oauth2/v2.0/authorize", + "grantTypes": [ + "authorizationCode" + ], + "clientCredentialsKeyVaultId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "clientIdSecretName": "apimclientid", + "clientSecretSecretName": "apimclientsecret", + "clientRegistrationEndpoint": "http://localhost", + "tokenEndpoint": "https://login.microsoftonline.com/651b43ce-ccb8-4301-b551-b04dd872d401/oauth2/v2.0/token" + } + ] + }, + "backends": { + "value": [ + { + "name": "backend", + "url": "http://echoapi.cloudapp.net/api", + "tls": { + "validateCertificateChain": false, + "validateCertificateName": false + } + } + ] + }, + "caches": { + "value": [ + { + "name": "westeurope", + "connectionString": "connectionstringtest", + "useFromLocation": "westeurope" + } + ] + }, + "identityProviders": { + "value": [ + { + "name": "aadProvider" + } + ] + }, + "namedValues": { + "value": [ + { + "name": "apimkey", + "displayName": "apimkey", + "secret": true + } + ] + }, + "policies": { + "value": [ + { + "value": " ", + "format": "xml" + } + ] + }, + "portalSettings": { + "value": [ + { + "name": "signin", + "properties": { + "enabled": false + } + }, + { + "name": "signup", + "properties": { + "enabled": false, + "termsOfService": { + "enabled": false, + "consentRequired": false + } + } + } + ] + }, + "products": { + "value": [ + { + "name": "Starter", + "subscriptionRequired": false, + "approvalRequired": false, + "apis": [ + { + "name": "echo-api" + } + ], + "groups": [ + { + "name": "developers" + } + ] + } + ] + }, + "subscriptions": { + "value": [ + { + "scope": "/apis", + "name": "testArmSubscriptionAllApis" + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/.parameters/parameters.json b/carml/1.0.0/Microsoft.ApiManagement/service/.parameters/parameters.json new file mode 100644 index 000000000..a7ae0692b --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/.parameters/parameters.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apim-x-001" + }, + "publisherEmail": { + "value": "apimgmt-noreply@mail.windowsazure.com" + }, + "publisherName": { + "value": "<>-az-amorg-x-001" + }, + "cuaId": { + "value": "00000-0-000000" + }, + "portalSettings": { + "value": [ + { + "name": "signin", + "properties": { + "enabled": false + } + }, + { + "name": "signup", + "properties": { + "enabled": false, + "termsOfService": { + "enabled": false, + "consentRequired": false + } + } + } + ] + }, + "policies": { + "value": [ + { + "value": " ", + "format": "xml" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/deploy.bicep new file mode 100644 index 000000000..b2cc5b3bb --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/deploy.bicep @@ -0,0 +1,35 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. API Version set name') +param name string = 'default' + +@description('Optional. API Version set properties') +param properties object = {} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource apiVersionSet 'Microsoft.ApiManagement/service/apiVersionSets@2021-08-01' = { + name: name + parent: service + properties: properties +} + +@description('The resource ID of the API Version set') +output resourceId string = apiVersionSet.id + +@description('The name of the API Version set') +output name string = apiVersionSet.name + +@description('The resource group the API Version set was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/readme.md new file mode 100644 index 000000000..9d2cb15f2 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/readme.md @@ -0,0 +1,30 @@ +# API Management Service API Version Sets `[Microsoft.ApiManagement/service/apiVersionSets]` + +This module deploys API Management Service APIs Version Set. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/apiVersionSets` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `default` | | Optional. API Version set name | +| `properties` | object | `{object}` | | Optional. API Version set properties | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API Version set | +| `resourceGroupName` | string | The resource group the API Version set was deployed into | +| `resourceId` | string | The resource ID of the API Version set | + +## Template references + +- [Service/Apiversionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apiVersionSets) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apiVersionSets/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/carml/1.0.0/Microsoft.ApiManagement/service/apis/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/apis/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apis/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/apis/deploy.bicep new file mode 100644 index 000000000..49dad325d --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/deploy.bicep @@ -0,0 +1,150 @@ +@description('Required. API revision identifier. Must be unique in the current API Management service instance. Non-current revision has ;rev=n as a suffix where n is the revision number.') +param name string + +@description('Optional. Array of Policies to apply to the Service API.') +param policies array = [] + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Describes the Revision of the API. If no value is provided, default revision 1 is created') +param apiRevision string = '' + +@description('Optional. Description of the API Revision.') +param apiRevisionDescription string = '' + +@description('Optional. Type of API to create. * http creates a SOAP to REST API * soap creates a SOAP pass-through API.') +@allowed([ + 'http' + 'soap' +]) +param apiType string = 'http' + +@description('Optional. Indicates the Version identifier of the API if the API is versioned') +param apiVersion string = '' + +@description('Optional. Indicates the Version identifier of the API version set') +param apiVersionSetId string = '' + +@description('Optional. Description of the API Version.') +param apiVersionDescription string = '' + +@description('Optional. Collection of authentication settings included into this API.') +param authenticationSettings object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Description of the API. May include HTML formatting tags.') +param apiDescription string = '' + +@description('Required. API name. Must be 1 to 300 characters long.') +@maxLength(300) +param displayName string + +@description('Optional. Format of the Content in which the API is getting imported.') +@allowed([ + 'wadl-xml' + 'wadl-link-json' + 'swagger-json' + 'swagger-link-json' + 'wsdl' + 'wsdl-link' + 'openapi' + 'openapi+json' + 'openapi-link' + 'openapi+json-link' +]) +param format string = 'openapi' + +@description('Optional. Indicates if API revision is current API revision.') +param isCurrent bool = true + +@description('Required. Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API.') +param path string + +@description('Optional. Describes on which protocols the operations in this API can be invoked. - HTTP or HTTPS') +param protocols array = [ + 'https' +] + +@description('Optional. Absolute URL of the backend service implementing this API. Cannot be more than 2000 characters long.') +@maxLength(2000) +param serviceUrl string = '' + +@description('Optional. API identifier of the source API.') +param sourceApiId string = '' + +@description('Optional. Protocols over which API is made available.') +param subscriptionKeyParameterNames object = {} + +@description('Optional. Specifies whether an API or Product subscription is required for accessing the API.') +param subscriptionRequired bool = false + +@description('Optional. Type of API.') +@allowed([ + 'http' + 'soap' +]) +param type string = 'http' + +@description('Optional. Content value when Importing an API.') +param value string = '' + +@description('Optional. Criteria to limit import of WSDL to a subset of the document.') +param wsdlSelector object = {} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource api 'Microsoft.ApiManagement/service/apis@2021-08-01' = { + name: name + parent: service + properties: { + apiRevision: !empty(apiRevision) ? apiRevision : null + apiRevisionDescription: !empty(apiRevisionDescription) ? apiRevisionDescription : null + apiType: !empty(apiType) ? apiType : null + apiVersion: !empty(apiVersion) ? apiVersion : null + apiVersionDescription: !empty(apiVersionDescription) ? apiVersionDescription : null + apiVersionSetId: !empty(apiVersionSetId) ? apiVersionSetId : null + authenticationSettings: authenticationSettings + description: apiDescription + displayName: displayName + format: !empty(value) ? format : null + isCurrent: isCurrent + path: path + protocols: protocols + serviceUrl: !empty(serviceUrl) ? serviceUrl : null + sourceApiId: !empty(sourceApiId) ? sourceApiId : null + subscriptionKeyParameterNames: !empty(subscriptionKeyParameterNames) ? subscriptionKeyParameterNames : null + subscriptionRequired: subscriptionRequired + type: type + value: !empty(value) ? value : null + wsdlSelector: wsdlSelector + } +} + +module policy 'policies/deploy.bicep' = [for (policy, index) in policies: { + name: '${deployment().name}-Policy-${index}' + params: { + apiManagementServiceName: apiManagementServiceName + apiName: api.name + format: contains(policy, 'format') ? policy.format : 'xml' + value: policy.value + } +}] + +@description('The name of the API management service API') +output name string = api.name + +@description('The resource ID of the API management service API') +output resourceId string = api.id + +@description('The resource group the API management service API was deployed to') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/deploy.bicep new file mode 100644 index 000000000..a232bba14 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/deploy.bicep @@ -0,0 +1,54 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. The name of the of the API.') +param apiName string + +@description('Optional. The name of the policy') +param name string = 'policy' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Format of the policyContent.') +@allowed([ + 'rawxml' + 'rawxml-link' + 'xml' + 'xml-link' +]) +param format string = 'xml' + +@description('Required. Contents of the Policy as defined by the format.') +param value string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName + + resource api 'apis@2021-08-01' existing = { + name: apiName + } +} + +resource policy 'Microsoft.ApiManagement/service/apis/policies@2021-08-01' = { + name: name + parent: service::api + properties: { + format: format + value: value + } +} + +@description('The resource ID of the API policy') +output resourceId string = policy.id + +@description('The name of the API policy') +output name string = policy.name + +@description('The resource group the API policy was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/readme.md new file mode 100644 index 000000000..d78e1f54d --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/readme.md @@ -0,0 +1,32 @@ +# API Management Service APIs Policies `[Microsoft.ApiManagement/service/apis/policies]` + +This module deploys API Management Service APIs policies. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/apis/policies` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `apiName` | string | | | Required. The name of the of the API. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `format` | string | `xml` | `[rawxml, rawxml-link, xml, xml-link]` | Optional. Format of the policyContent. | +| `name` | string | `policy` | | Optional. The name of the policy | +| `value` | string | | | Required. Contents of the Policy as defined by the format. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API policy | +| `resourceGroupName` | string | The resource group the API policy was deployed into | +| `resourceId` | string | The resource ID of the API policy | + +## Template references + +- [Service/Apis/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis/policies) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/policies/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/carml/1.0.0/Microsoft.ApiManagement/service/apis/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/apis/readme.md new file mode 100644 index 000000000..b57b0cc3c --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/readme.md @@ -0,0 +1,75 @@ +# API Management Service APIs `[Microsoft.ApiManagement/service/apis]` + +This module deploys API Management Service APIs. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apis/policies` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiDescription` | string | | | Optional. Description of the API. May include HTML formatting tags. | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `apiRevision` | string | | | Optional. Describes the Revision of the API. If no value is provided, default revision 1 is created | +| `apiRevisionDescription` | string | | | Optional. Description of the API Revision. | +| `apiType` | string | `http` | `[http, soap]` | Optional. Type of API to create. * http creates a SOAP to REST API * soap creates a SOAP pass-through API. | +| `apiVersion` | string | | | Optional. Indicates the Version identifier of the API if the API is versioned | +| `apiVersionDescription` | string | | | Optional. Description of the API Version. | +| `apiVersionSetId` | string | | | Optional. Indicates the Version identifier of the API version set | +| `authenticationSettings` | object | `{object}` | | Optional. Collection of authentication settings included into this API. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `displayName` | string | | | Required. API name. Must be 1 to 300 characters long. | +| `format` | string | `openapi` | `[wadl-xml, wadl-link-json, swagger-json, swagger-link-json, wsdl, wsdl-link, openapi, openapi+json, openapi-link, openapi+json-link]` | Optional. Format of the Content in which the API is getting imported. | +| `isCurrent` | bool | `True` | | Optional. Indicates if API revision is current API revision. | +| `name` | string | | | Required. API revision identifier. Must be unique in the current API Management service instance. Non-current revision has ;rev=n as a suffix where n is the revision number. | +| `path` | string | | | Required. Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API. | +| `policies` | _[policies](policies/readme.md)_ array | `[]` | | Optional. Array of Policies to apply to the Service API. | +| `protocols` | array | `[https]` | | Optional. Describes on which protocols the operations in this API can be invoked. - HTTP or HTTPS | +| `serviceUrl` | string | | | Optional. Absolute URL of the backend service implementing this API. Cannot be more than 2000 characters long. | +| `sourceApiId` | string | | | Optional. API identifier of the source API. | +| `subscriptionKeyParameterNames` | object | `{object}` | | Optional. Protocols over which API is made available. | +| `subscriptionRequired` | bool | | | Optional. Specifies whether an API or Product subscription is required for accessing the API. | +| `type` | string | `http` | `[http, soap]` | Optional. Type of API. | +| `value` | string | | | Optional. Content value when Importing an API. | +| `wsdlSelector` | object | `{object}` | | Optional. Criteria to limit import of WSDL to a subset of the document. | + +### Parameter Usage: `apiVersionSet` + +```json +"apiVersionSet":{ + "value":{ + "name":"", //Required. API Version Set identifier. Must be unique in the current API Management service instance. + "properties":{ + "description": "string", //Description of API Version Set. + "versionQueryName": "string", //Optional. Name of query parameter that indicates the API Version if versioningScheme is set to query. + "versionHeaderName": "string", //Optional. Name of HTTP header parameter that indicates the API Version if versioningScheme is set to header. + "displayName": "string", //Required. Name of API Version Set + "versioningScheme": "string" //Required. An value that determines where the API Version identifer will be located in a HTTP request. - Segment, Query, Header + } + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service API | +| `resourceGroupName` | string | The resource group the API management service API was deployed to | +| `resourceId` | string | The resource ID of the API management service API | + +## Template references + +- [Service/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis) +- [Service/Apis/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis/policies) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/apis/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/apis/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/apis/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/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/deploy.bicep new file mode 100644 index 000000000..4296f8108 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/deploy.bicep @@ -0,0 +1,107 @@ +@description('Required. Identifier of the authorization server.') +param name string + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. OAuth authorization endpoint. See .') +param authorizationEndpoint string + +@description('Optional. HTTP verbs supported by the authorization endpoint. GET must be always present. POST is optional. - HEAD, OPTIONS, TRACE, GET, POST, PUT, PATCH, DELETE') +param authorizationMethods array = [ + 'GET' +] + +@description('Optional. Specifies the mechanism by which access token is passed to the API. - authorizationHeader or query') +param bearerTokenSendingMethods array = [ + 'authorizationHeader' +] + +@description('Optional. Method of authentication supported by the token endpoint of this authorization server. Possible values are Basic and/or Body. When Body is specified, client credentials and other parameters are passed within the request body in the application/x-www-form-urlencoded format. - Basic or Body') +param clientAuthenticationMethod array = [ + 'Basic' +] + +@description('Required. Client or app ID registered with this authorization server.') +@secure() +param clientId string + +@description('Optional. Optional reference to a page where client or app registration for this authorization server is performed. Contains absolute URL to entity being referenced.') +param clientRegistrationEndpoint string = '' + +@description('Required. Client or app secret registered with this authorization server. This property will not be filled on \'GET\' operations! Use \'/listSecrets\' POST request to get the value.') +@secure() +param clientSecret string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Access token scope that is going to be requested by default. Can be overridden at the API level. Should be provided in the form of a string containing space-delimited values.') +param defaultScope string = '' + +@description('Optional. Description of the authorization server. Can contain HTML formatting tags.') +param serverDescription string = '' + +@description('Required. Form of an authorization grant, which the client uses to request the access token. - authorizationCode, implicit, resourceOwnerPassword, clientCredentials') +param grantTypes array + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner password.') +param resourceOwnerPassword string = '' + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner username.') +param resourceOwnerUsername string = '' + +@description('Optional. If true, authorization server will include state parameter from the authorization request to its response. Client may use state parameter to raise protocol security.') +param supportState bool = false + +@description('Optional. Additional parameters required by the token endpoint of this authorization server represented as an array of JSON objects with name and value string properties, i.e. {"name" : "name value", "value": "a value"}. - TokenBodyParameterContract object') +param tokenBodyParameters array = [] + +@description('Optional. OAuth token endpoint. Contains absolute URI to entity being referenced.') +param tokenEndpoint string = '' + +var defaultAuthorizationMethods = [ + 'GET' +] +var setAuthorizationMethods = union(authorizationMethods, defaultAuthorizationMethods) + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource authorizationServer 'Microsoft.ApiManagement/service/authorizationServers@2021-08-01' = { + name: name + parent: service + properties: { + description: serverDescription + authorizationMethods: setAuthorizationMethods + clientAuthenticationMethod: clientAuthenticationMethod + tokenBodyParameters: tokenBodyParameters + tokenEndpoint: tokenEndpoint + supportState: supportState + defaultScope: defaultScope + bearerTokenSendingMethods: bearerTokenSendingMethods + resourceOwnerUsername: resourceOwnerUsername + resourceOwnerPassword: resourceOwnerPassword + displayName: name + clientRegistrationEndpoint: clientRegistrationEndpoint + authorizationEndpoint: authorizationEndpoint + grantTypes: grantTypes + clientId: clientId + clientSecret: clientSecret + } +} + +@description('The name of the API management service authorization server') +output name string = authorizationServer.name + +@description('The resource ID of the API management service authorization server') +output resourceId string = authorizationServer.id + +@description('The resource group the API management service authorization server was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/readme.md new file mode 100644 index 000000000..17429c386 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/readme.md @@ -0,0 +1,50 @@ +# API Management Service Authorization Servers `[Microsoft.ApiManagement/service/authorizationServers]` + +This module deploys API Management Service Authorization Servers. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/authorizationServers` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `authorizationEndpoint` | string | | | Required. OAuth authorization endpoint. See . | +| `authorizationMethods` | array | `[GET]` | | Optional. HTTP verbs supported by the authorization endpoint. GET must be always present. POST is optional. - HEAD, OPTIONS, TRACE, GET, POST, PUT, PATCH, DELETE | +| `bearerTokenSendingMethods` | array | `[authorizationHeader]` | | Optional. Specifies the mechanism by which access token is passed to the API. - authorizationHeader or query | +| `clientAuthenticationMethod` | array | `[Basic]` | | Optional. Method of authentication supported by the token endpoint of this authorization server. Possible values are Basic and/or Body. When Body is specified, client credentials and other parameters are passed within the request body in the application/x-www-form-urlencoded format. - Basic or Body | +| `clientId` | secureString | | | Required. Client or app ID registered with this authorization server. | +| `clientRegistrationEndpoint` | string | | | Optional. Optional reference to a page where client or app registration for this authorization server is performed. Contains absolute URL to entity being referenced. | +| `clientSecret` | secureString | | | Required. Client or app secret registered with this authorization server. This property will not be filled on 'GET' operations! Use '/listSecrets' POST request to get the value. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `defaultScope` | string | | | Optional. Access token scope that is going to be requested by default. Can be overridden at the API level. Should be provided in the form of a string containing space-delimited values. | +| `grantTypes` | array | | | Required. Form of an authorization grant, which the client uses to request the access token. - authorizationCode, implicit, resourceOwnerPassword, clientCredentials | +| `name` | string | | | Required. Identifier of the authorization server. | +| `resourceOwnerPassword` | string | | | Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner password. | +| `resourceOwnerUsername` | string | | | Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner username. | +| `serverDescription` | string | | | Optional. Description of the authorization server. Can contain HTML formatting tags. | +| `supportState` | bool | | | Optional. If true, authorization server will include state parameter from the authorization request to its response. Client may use state parameter to raise protocol security. | +| `tokenBodyParameters` | array | `[]` | | Optional. Additional parameters required by the token endpoint of this authorization server represented as an array of JSON objects with name and value string properties, i.e. {"name" : "name value", "value": "a value"}. - TokenBodyParameterContract object | +| `tokenEndpoint` | string | | | Optional. OAuth token endpoint. Contains absolute URI to entity being referenced. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service authorization server | +| `resourceGroupName` | string | The resource group the API management service authorization server was deployed into | +| `resourceId` | string | The resource ID of the API management service authorization server | + +## Template references + +- [Service/Authorizationservers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/authorizationServers) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/authorizationServers/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/carml/1.0.0/Microsoft.ApiManagement/service/backends/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/backends/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/backends/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/backends/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/backends/deploy.bicep new file mode 100644 index 000000000..f588942ad --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/backends/deploy.bicep @@ -0,0 +1,74 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. Backend Name.') +param name string + +@description('Optional. Backend Credentials Contract Properties.') +param credentials object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Backend Description.') +param backendDescription string = '' + +@description('Optional. Backend communication protocol. - http or soap') +param protocol string = 'http' + +@description('Optional. Backend Proxy Contract Properties') +param proxy object = {} + +@description('Optional. Management Uri of the Resource in External System. This URL can be the Arm Resource ID of Logic Apps, Function Apps or API Apps.') +param resourceId string = '' + +@description('Optional. Backend Service Fabric Cluster Properties.') +param serviceFabricCluster object = {} + +@description('Optional. Backend Title.') +param title string = '' + +@description('Optional. Backend TLS Properties') +param tls object = { + validateCertificateChain: false + validateCertificateName: false +} + +@description('Required. Runtime URL of the Backend.') +param url string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource backend 'Microsoft.ApiManagement/service/backends@2021-08-01' = { + name: name + parent: service + properties: { + title: !empty(title) ? title : null + description: !empty(backendDescription) ? backendDescription : null + resourceId: !empty(resourceId) ? resourceId : null + properties: { + serviceFabricCluster: !empty(serviceFabricCluster) ? serviceFabricCluster : null + } + credentials: !empty(credentials) ? credentials : null + proxy: !empty(proxy) ? proxy : null + tls: !empty(tls) ? tls : null + url: url + protocol: protocol + } +} + +@description('The resource ID of the API management service backend') +output resourceId string = backend.id + +@description('The name of the API management service backend') +output name string = backend.name + +@description('The resource group the API management service backend was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/backends/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/backends/readme.md new file mode 100644 index 000000000..fcb1eb25d --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/backends/readme.md @@ -0,0 +1,131 @@ +# API Management Service Backends `[Microsoft.ApiManagement/service/backends]` + +This module deploys API Management Service Backends. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/backends` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `backendDescription` | string | | | Optional. Backend Description. | +| `credentials` | object | `{object}` | | Optional. Backend Credentials Contract Properties. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Backend Name. | +| `protocol` | string | `http` | | Optional. Backend communication protocol. - http or soap | +| `proxy` | object | `{object}` | | Optional. Backend Proxy Contract Properties | +| `resourceId` | string | | | Optional. Management Uri of the Resource in External System. This URL can be the Arm Resource ID of Logic Apps, Function Apps or API Apps. | +| `serviceFabricCluster` | object | `{object}` | | Optional. Backend Service Fabric Cluster Properties. | +| `title` | string | | | Optional. Backend Title. | +| `tls` | object | `{object}` | | Optional. Backend TLS Properties | +| `url` | string | | | Required. Runtime URL of the Backend. | + +### Parameters - credentials + +| Parameter Name| Type | Default Value | Possible values | Description | +| :-- | :-- | :--- | :-- | :- | +| `certificate` | array | | | Optional. List of Client Certificate Thumbprint. - string | +| `query` | object | | | Optional. Query Parameter description. | +| `header` | object | | | Optional. Header Parameter description. | +| `authorization` | object | | | Optional. Authorization header authentication | + +### Parameter Usage: `credentials` + +```json +"credentials": { + "value":{ + "certificate": [ + "string" + ], + "query": {}, + "header": {}, + "authorization": { + "scheme": "Authentication Scheme name.-string", + "parameter": "Authentication Parameter value. - string" + } + } +} +``` + +### Parameter Usage: `proxy` + +| Parameter Name | Type | Default Value | Possible values | Description | +| :- | :- | :- | :- | :- | +| `url` | string | | | WebProxy Server AbsoluteUri property which includes the entire URI stored in the URI instance, including all fragments and query strings.| +| `username` | string | | | Username to connect to the WebProxy server| +| `password`| string | | | Password to connect to the WebProxy Server| + +```json +"proxy": { + "value":{ + "url": "string", + "username": "string", + "password": "string" + } +} +``` + +### Parameter Usage: `serviceFabricCluster` + +| Parameter Name | Type | Default Value | Possible values | Description | +| :-- | :-- | :--- | :-- | :- | +| `clientCertificatethumbprint` | string | | | Required (if this object is used).The client certificate thumbprint for the management endpoint.| +| `maxPartitionResolutionRetries` | integer | | | Optional. Maximum number of retries while attempting resolve the partition. | +| `managementEndpoints` | array | | | Required (if this object is used). The cluster management endpoint. - string| +| `serverCertificateThumbprints`| array | | | Optional. Thumbprints of certificates cluster management service uses for TLS communication - string| +| `serverX509Names` | array | | | Optional. Server X509 Certificate Names Collection| + +```json +"serviceFabricCluster": { + "value":{ + "clientCertificatethumbprint": "string", + "maxPartitionResolutionRetries": "integer", + "managementEndpoints": [ + "string" + ], + "serverCertificateThumbprints": [ + "string" + ], + "serverX509Names": [ + { + "name": "Common Name of the Certificate.- string", + "issuerCertificateThumbprint": "Thumbprint for the Issuer of the Certificate. - string" + } + ] + } +} +``` + +### Parameter Usage: `tls` + +```json +"tls": { + "value":{ + "validateCertificateChain": "Flag indicating whether SSL certificate chain validation should be done when using self-signed certificates for this backend host. - boolean", + "validateCertificateName": "Flag indicating whether SSL certificate name validation should be done when using self-signed certificates for this backend host. - boolean" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service backend | +| `resourceGroupName` | string | The resource group the API management service backend was deployed into | +| `resourceId` | string | The resource ID of the API management service backend | + +## Template references + +- [Service/Backends](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/backends) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/backends/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/backends/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/backends/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/carml/1.0.0/Microsoft.ApiManagement/service/caches/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/caches/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/caches/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/caches/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/caches/deploy.bicep new file mode 100644 index 000000000..d3cd88147 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/caches/deploy.bicep @@ -0,0 +1,49 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. Identifier of the Cache entity. Cache identifier (should be either \'default\' or valid Azure region identifier).') +param name string + +@description('Required. Runtime connection string to cache. Can be referenced by a named value like so, {{}}') +param connectionString string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Cache description') +param cacheDescription string = '' + +@description('Optional. Original uri of entity in external system cache points to.') +param resourceId string = '' + +@description('Required. Location identifier to use cache from (should be either \'default\' or valid Azure region identifier)') +param useFromLocation string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource cache 'Microsoft.ApiManagement/service/caches@2021-08-01' = { + name: name + parent: service + properties: { + description: !empty(cacheDescription) ? cacheDescription : null + connectionString: connectionString + useFromLocation: useFromLocation + resourceId: !empty(resourceId) ? resourceId : null + } +} + +@description('The resource ID of the API management service cache') +output resourceId string = cache.id + +@description('The name of the API management service cache') +output name string = cache.name + +@description('The resource group the API management service cache was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/caches/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/caches/readme.md new file mode 100644 index 000000000..78f948c8f --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/caches/readme.md @@ -0,0 +1,39 @@ +# API Management Service Cache `[Microsoft.ApiManagement/service/caches]` + +This module deploys an API Management Service Cache. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/caches` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cacheDescription` | string | | | Optional. Cache description | +| `connectionString` | string | | | Required. Runtime connection string to cache. Can be referenced by a named value like so, {{}} | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Identifier of the Cache entity. Cache identifier (should be either 'default' or valid Azure region identifier). | +| `resourceId` | string | | | Optional. Original uri of entity in external system cache points to. | +| `useFromLocation` | string | | | Required. Location identifier to use cache from (should be either 'default' or valid Azure region identifier) | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service cache | +| `resourceGroupName` | string | The resource group the API management service cache was deployed into | +| `resourceId` | string | The resource ID of the API management service cache | + +## Template references + +- [Service/Caches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/caches) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/caches/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/caches/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/caches/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/carml/1.0.0/Microsoft.ApiManagement/service/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/deploy.bicep new file mode 100644 index 000000000..347272115 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/deploy.bicep @@ -0,0 +1,440 @@ +@description('Optional. Additional datacenter locations of the API Management service.') +param additionalLocations array = [] + +@description('Required. The name of the of the API Management service.') +param name string + +@description('Optional. List of Certificates that need to be installed in the API Management service. Max supported certificates that can be installed is 10.') +@maxLength(10) +param certificates array = [] + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Custom properties of the API Management service.') +param customProperties object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Property only valid for an API Management service deployed in multiple locations. This can be used to disable the gateway in master region.') +param disableGateway bool = false + +@description('Optional. Property only meant to be used for Consumption SKU Service. This enforces a client certificate to be presented on each request to the gateway. This also enables the ability to authenticate the certificate in the policy on the gateway.') +param enableClientCertificate bool = false + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Custom hostname configuration of the API Management service.') +param hostnameConfigurations array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Limit control plane API calls to API Management service with version equal to or newer than this value.') +param minApiVersion string = '' + +@description('Optional. The notification sender email address for the service.') +param notificationSenderEmail string = 'apimgmt-noreply@mail.windowsazure.com' + +@description('Required. The email address of the owner of the service.') +param publisherEmail string + +@description('Required. The name of the owner of the service.') +param publisherName string + +@description('Optional. Undelete API Management Service if it was previously soft-deleted. If this flag is specified and set to True all other properties will be ignored.') +param restore bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The pricing tier of this API Management service.') +@allowed([ + 'Consumption' + 'Developer' + 'Basic' + 'Standard' + 'Premium' +]) +param sku string = 'Developer' + +@description('Optional. The instance size of this API Management service.') +@allowed([ + 1 + 2 +]) +param skuCount int = 1 + +@description('Optional. The full resource ID of a subnet in a virtual network to deploy the API Management service in.') +param subnetResourceId string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The type of VPN in which API Management service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only.') +@allowed([ + 'None' + 'External' + 'Internal' +]) +param virtualNetworkType string = 'None' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. A list of availability zones denoting where the resource needs to come from.') +param zones array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'GatewayLogs' +]) +param logsToEnable array = [ + 'GatewayLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] +@description('Optional. Necessary to create a new GUID.') +param newGuidValue string = newGuid() + +@description('Optional. APIs.') +param apis array = [] +@description('Optional. API Version Sets.') +param apiVersionSets array = [] +@description('Optional. Authorization servers.') +param authorizationServers array = [] +@description('Optional. Backends.') +param backends array = [] +@description('Optional. Caches.') +param caches array = [] +@description('Optional. Identity providers.') +param identityProviders array = [] +@description('Optional. Named values.') +param namedValues array = [] +@description('Optional. Policies.') +param policies array = [] +@description('Optional. Portal settings.') +param portalSettings array = [] +@description('Optional. Products.') +param products array = [] +@description('Optional. Subscriptions.') +param subscriptions array = [] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource apiManagementService 'Microsoft.ApiManagement/service@2021-08-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + capacity: skuCount + } + zones: zones + identity: identity + properties: { + publisherEmail: publisherEmail + publisherName: publisherName + notificationSenderEmail: notificationSenderEmail + hostnameConfigurations: hostnameConfigurations + additionalLocations: additionalLocations + customProperties: customProperties + certificates: certificates + enableClientCertificate: enableClientCertificate ? true : null + disableGateway: disableGateway + virtualNetworkType: virtualNetworkType + virtualNetworkConfiguration: !empty(subnetResourceId) ? json('{"subnetResourceId": "${subnetResourceId}"}') : null + apiVersionConstraint: !empty(minApiVersion) ? json('{"minApiVersion": "${minApiVersion}"}') : null + restore: restore + } +} + +module apis_resource 'apis/deploy.bicep' = [for (api, index) in apis: { + name: '${uniqueString(deployment().name, location)}-Apim-Api-${index}' + params: { + apiManagementServiceName: apiManagementService.name + displayName: api.displayName + name: api.name + path: api.path + apiDescription: contains(api, 'apiDescription') ? api.apiDescription : '' + apiRevision: contains(api, 'apiRevision') ? api.apiRevision : '' + apiRevisionDescription: contains(api, 'apiRevisionDescription') ? api.apiRevisionDescription : '' + apiType: contains(api, 'apiType') ? api.apiType : 'http' + apiVersion: contains(api, 'apiVersion') ? api.apiVersion : '' + apiVersionDescription: contains(api, 'apiVersionDescription') ? api.apiVersionDescription : '' + apiVersionSetId: contains(api, 'apiVersionSetId') ? api.apiVersionSetId : '' + authenticationSettings: contains(api, 'authenticationSettings') ? api.authenticationSettings : {} + format: contains(api, 'format') ? api.format : 'openapi' + isCurrent: contains(api, 'isCurrent') ? api.isCurrent : true + protocols: contains(api, 'protocols') ? api.protocols : [ + 'https' + ] + policies: contains(api, 'policies') ? api.policies : [] + serviceUrl: contains(api, 'serviceUrl') ? api.serviceUrl : '' + sourceApiId: contains(api, 'sourceApiId') ? api.sourceApiId : '' + subscriptionKeyParameterNames: contains(api, 'subscriptionKeyParameterNames') ? api.subscriptionKeyParameterNames : {} + subscriptionRequired: contains(api, 'subscriptionRequired') ? api.subscriptionRequired : false + type: contains(api, 'type') ? api.type : 'http' + value: contains(api, 'value') ? api.value : '' + wsdlSelector: contains(api, 'wsdlSelector') ? api.wsdlSelector : {} + } + dependsOn: [ + apiVersionSet_resource + ] +}] + +module apiVersionSet_resource 'apiVersionSets/deploy.bicep' = [for (apiVersionSet, index) in apiVersionSets: { + name: '${uniqueString(deployment().name, location)}-Apim-ApiVersionSet-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: apiVersionSet.name + properties: contains(apiVersionSet, 'properties') ? apiVersionSet.properties : {} + } +}] + +module authorizationServers_resource '.bicep/nested_authorizationServers.bicep' = [for (authorizationServer, index) in authorizationServers: { + name: '${uniqueString(deployment().name, location)}-Apim-AuthorizationServer-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: authorizationServer.name + authorizationEndpoint: authorizationServer.authorizationEndpoint + authorizationMethods: contains(authorizationServer, 'authorizationMethods') ? authorizationServer.authorizationMethods : [ + 'GET' + ] + bearerTokenSendingMethods: contains(authorizationServer, 'bearerTokenSendingMethods') ? authorizationServer.bearerTokenSendingMethods : [ + 'authorizationHeader' + ] + clientAuthenticationMethod: contains(authorizationServer, 'clientAuthenticationMethod') ? authorizationServer.clientAuthenticationMethod : [ + 'Basic' + ] + clientCredentialsKeyVaultId: authorizationServer.clientCredentialsKeyVaultId + clientIdSecretName: authorizationServer.clientIdSecretName + clientSecretSecretName: authorizationServer.clientSecretSecretName + clientRegistrationEndpoint: contains(authorizationServer, 'clientRegistrationEndpoint') ? authorizationServer.clientRegistrationEndpoint : '' + defaultScope: contains(authorizationServer, 'defaultScope') ? authorizationServer.defaultScope : '' + grantTypes: authorizationServer.grantTypes + resourceOwnerPassword: contains(authorizationServer, 'resourceOwnerPassword') ? authorizationServer.resourceOwnerPassword : '' + resourceOwnerUsername: contains(authorizationServer, 'resourceOwnerUsername') ? authorizationServer.resourceOwnerUsername : '' + serverDescription: contains(authorizationServer, 'serverDescription') ? authorizationServer.serverDescription : '' + supportState: contains(authorizationServer, 'supportState') ? authorizationServer.supportState : false + tokenBodyParameters: contains(authorizationServer, 'tokenBodyParameters') ? authorizationServer.tokenBodyParameters : [] + tokenEndpoint: contains(authorizationServer, 'tokenEndpoint') ? authorizationServer.tokenEndpoint : '' + } +}] + +module backends_resource 'backends/deploy.bicep' = [for (backend, index) in backends: { + name: '${uniqueString(deployment().name, location)}-Apim-Backend-${index}' + params: { + apiManagementServiceName: apiManagementService.name + url: contains(backend, 'url') ? backend.url : '' + backendDescription: contains(backend, 'backendDescription') ? backend.backendDescription : '' + credentials: contains(backend, 'credentials') ? backend.credentials : {} + name: backend.name + protocol: contains(backend, 'protocol') ? backend.protocol : 'http' + proxy: contains(backend, 'proxy') ? backend.proxy : {} + resourceId: contains(backend, 'resourceId') ? backend.resourceId : '' + serviceFabricCluster: contains(backend, 'serviceFabricCluster') ? backend.serviceFabricCluster : {} + title: contains(backend, 'title') ? backend.title : '' + tls: contains(backend, 'tls') ? backend.tls : { + validateCertificateChain: false + validateCertificateName: false + } + } +}] + +module caches_resource 'caches/deploy.bicep' = [for (cache, index) in caches: { + name: '${uniqueString(deployment().name, location)}-Apim-Cache-${index}' + params: { + apiManagementServiceName: apiManagementService.name + cacheDescription: contains(cache, 'cacheDescription') ? cache.cacheDescription : '' + connectionString: cache.connectionString + name: cache.name + resourceId: contains(cache, 'resourceId') ? cache.resourceId : '' + useFromLocation: cache.useFromLocation + } +}] + +module identityProvider_resource 'identityProviders/deploy.bicep' = [for (identityProvider, index) in identityProviders: { + name: '${uniqueString(deployment().name, location)}-Apim-IdentityProvider-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: identityProvider.name + enableIdentityProviders: contains(identityProvider, 'enableIdentityProviders') ? identityProvider.enableIdentityProviders : false + identityProviderAllowedTenants: contains(identityProvider, 'identityProviderAllowedTenants') ? identityProvider.identityProviderAllowedTenants : [] + identityProviderAuthority: contains(identityProvider, 'identityProviderAuthority') ? identityProvider.identityProviderAuthority : '' + identityProviderClientId: contains(identityProvider, 'identityProviderClientId') ? identityProvider.identityProviderClientId : '' + identityProviderClientSecret: contains(identityProvider, 'identityProviderClientSecret') ? identityProvider.identityProviderClientSecret : '' + identityProviderPasswordResetPolicyName: contains(identityProvider, 'identityProviderPasswordResetPolicyName') ? identityProvider.identityProviderPasswordResetPolicyName : '' + identityProviderProfileEditingPolicyName: contains(identityProvider, 'identityProviderProfileEditingPolicyName') ? identityProvider.identityProviderProfileEditingPolicyName : '' + identityProviderSignInPolicyName: contains(identityProvider, 'identityProviderSignInPolicyName') ? identityProvider.identityProviderSignInPolicyName : '' + identityProviderSignInTenant: contains(identityProvider, 'identityProviderSignInTenant') ? identityProvider.identityProviderSignInTenant : '' + identityProviderSignUpPolicyName: contains(identityProvider, 'identityProviderSignUpPolicyName') ? identityProvider.identityProviderSignUpPolicyName : '' + identityProviderType: contains(identityProvider, 'identityProviderType') ? identityProvider.identityProviderType : 'aad' + } +}] + +module namedValues_resource 'namedValues/deploy.bicep' = [for (namedValue, index) in namedValues: { + name: '${uniqueString(deployment().name, location)}-Apim-NamedValue-${index}' + params: { + apiManagementServiceName: apiManagementService.name + displayName: namedValue.displayName + keyVault: contains(namedValue, 'keyVault') ? namedValue.keyVault : {} + name: namedValue.name + namedValueTags: contains(namedValue, 'namedValueTags') ? namedValue.namedValueTags : [] + secret: contains(namedValue, 'secret') ? namedValue.secret : false + value: contains(namedValue, 'value') ? namedValue.value : newGuidValue + } +}] + +module portalSettings_resource 'portalsettings/deploy.bicep' = [for (portalSetting, index) in portalSettings: { + name: '${uniqueString(deployment().name, location)}-Apim-PortalSetting-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: portalSetting.name + properties: contains(portalSetting, 'properties') ? portalSetting.properties : {} + } +}] + +module policy_resource 'policies/deploy.bicep' = [for (policy, index) in policies: { + name: '${uniqueString(deployment().name, location)}-Apim-Policy-${index}' + params: { + apiManagementServiceName: apiManagementService.name + value: policy.value + format: contains(policy, 'format') ? policy.format : 'xml' + } +}] + +module products_resource 'products/deploy.bicep' = [for (product, index) in products: { + name: '${uniqueString(deployment().name, location)}-Apim-Product-${index}' + params: { + apiManagementServiceName: apiManagementService.name + apis: contains(product, 'apis') ? product.apis : [] + approvalRequired: contains(product, 'approvalRequired') ? product.approvalRequired : false + groups: contains(product, 'groups') ? product.groups : [] + name: product.name + productDescription: contains(product, 'productDescription') ? product.productDescription : '' + state: contains(product, 'state') ? product.state : 'published' + subscriptionRequired: contains(product, 'subscriptionRequired') ? product.subscriptionRequired : false + subscriptionsLimit: contains(product, 'subscriptionsLimit') ? product.subscriptionsLimit : 1 + terms: contains(product, 'terms') ? product.terms : '' + } + dependsOn: [ + apis_resource + ] +}] + +module subscriptions_resource 'subscriptions/deploy.bicep' = [for (subscription, index) in subscriptions: { + name: '${uniqueString(deployment().name, location)}-Apim-Subscription-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: contains(subscription, 'name') ? subscription.name : '' + allowTracing: contains(subscription, 'allowTracing') ? subscription.allowTracing : false + ownerId: contains(subscription, 'ownerId') ? subscription.ownerId : '' + primaryKey: contains(subscription, 'primaryKey') ? subscription.primaryKey : '' + scope: contains(subscription, 'scope') ? subscription.scope : '/apis' + secondaryKey: contains(subscription, 'secondaryKey') ? subscription.secondaryKey : '' + state: contains(subscription, 'state') ? subscription.state : '' + } +}] + +resource apiManagementService_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${apiManagementService.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: apiManagementService +} + +resource apiManagementService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${apiManagementService.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: apiManagementService +} + +module apiManagementService_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Apim-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: apiManagementService.id + } +}] + +@description('The name of the API management service') +output name string = apiManagementService.name + +@description('The resource ID of the API management service') +output resourceId string = apiManagementService.id + +@description('The resource group the API management service was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(apiManagementService.identity, 'principalId') ? apiManagementService.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/deploy.bicep new file mode 100644 index 000000000..d872e9ac0 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/deploy.bicep @@ -0,0 +1,87 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Used to enable the deployment of the identityProviders child resource.') +param enableIdentityProviders bool = false + +@description('Optional. List of Allowed Tenants when configuring Azure Active Directory login. - string') +param identityProviderAllowedTenants array = [] + +@description('Optional. OpenID Connect discovery endpoint hostname for AAD or AAD B2C.') +param identityProviderAuthority string = '' + +@description('Optional. Client ID of the Application in the external Identity Provider. Required if identity provider is used.') +param identityProviderClientId string = '' + +@description('Optional. Client secret of the Application in external Identity Provider, used to authenticate login request. Required if identity provider is used.') +@secure() +param identityProviderClientSecret string = '' + +@description('Optional. Password Reset Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderPasswordResetPolicyName string = '' + +@description('Optional. Profile Editing Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderProfileEditingPolicyName string = '' + +@description('Optional. Signin Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderSignInPolicyName string = '' + +@description('Optional. The TenantId to use instead of Common when logging into Active Directory') +param identityProviderSignInTenant string = '' + +@description('Optional. Signup Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderSignUpPolicyName string = '' + +@description('Optional. Identity Provider Type identifier.') +@allowed([ + 'aad' + 'aadB2C' + 'facebook' + 'google' + 'microsoft' + 'twitter' +]) +param identityProviderType string = 'aad' + +@description('Required. Identity provider name') +param name string + +var isAadB2C = (identityProviderType == 'aadB2C') + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource identityProvider 'Microsoft.ApiManagement/service/identityProviders@2021-08-01' = if (enableIdentityProviders) { + name: name + parent: service + properties: { + type: identityProviderType + signinTenant: identityProviderSignInTenant + allowedTenants: identityProviderAllowedTenants + authority: identityProviderAuthority + signupPolicyName: isAadB2C ? identityProviderSignUpPolicyName : null + signinPolicyName: isAadB2C ? identityProviderSignInPolicyName : null + profileEditingPolicyName: isAadB2C ? identityProviderProfileEditingPolicyName : null + passwordResetPolicyName: isAadB2C ? identityProviderPasswordResetPolicyName : null + clientId: identityProviderClientId + clientSecret: identityProviderClientSecret + } +} + +@description('The resource ID of the API management service identity provider') +output resourceId string = identityProvider.id + +@description('The name of the API management service identity provider') +output name string = identityProvider.name + +@description('The resource group the API management service identity provider was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/readme.md new file mode 100644 index 000000000..3f24fd36d --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/readme.md @@ -0,0 +1,40 @@ +# API Management Service Identity Providers `[Microsoft.ApiManagement/service/identityProviders]` + +This module deploys API Management Service Identity Provider. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/identityProviders` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enableIdentityProviders` | bool | | | Optional. Used to enable the deployment of the identityProviders child resource. | +| `identityProviderAllowedTenants` | array | `[]` | | Optional. List of Allowed Tenants when configuring Azure Active Directory login. - string | +| `identityProviderAuthority` | string | | | Optional. OpenID Connect discovery endpoint hostname for AAD or AAD B2C. | +| `identityProviderClientId` | string | | | Optional. Client ID of the Application in the external Identity Provider. Required if identity provider is used. | +| `identityProviderClientSecret` | secureString | | | Optional. Client secret of the Application in external Identity Provider, used to authenticate login request. Required if identity provider is used. | +| `identityProviderPasswordResetPolicyName` | string | | | Optional. Password Reset Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderProfileEditingPolicyName` | string | | | Optional. Profile Editing Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderSignInPolicyName` | string | | | Optional. Signin Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderSignInTenant` | string | | | Optional. The TenantId to use instead of Common when logging into Active Directory | +| `identityProviderSignUpPolicyName` | string | | | Optional. Signup Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderType` | string | `aad` | `[aad, aadB2C, facebook, google, microsoft, twitter]` | Optional. Identity Provider Type identifier. | +| `name` | string | | | Required. Identity provider name | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service identity provider | +| `resourceGroupName` | string | The resource group the API management service identity provider was deployed into | +| `resourceId` | string | The resource ID of the API management service identity provider | + +## Template references + +- [Service/Identityproviders](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/identityProviders) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/identityProviders/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/carml/1.0.0/Microsoft.ApiManagement/service/namedValues/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/namedValues/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/namedValues/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/policies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/policies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/policies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/policies/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/policies/deploy.bicep new file mode 100644 index 000000000..727aa22ed --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/policies/deploy.bicep @@ -0,0 +1,47 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. The name of the policy') +param name string = 'policy' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Format of the policyContent.') +@allowed([ + 'rawxml' + 'rawxml-link' + 'xml' + 'xml-link' +]) +param format string = 'xml' + +@description('Required. Contents of the Policy as defined by the format.') +param value string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource policy 'Microsoft.ApiManagement/service/policies@2021-08-01' = { + name: name + parent: service + properties: { + format: format + value: value + } +} + +@description('The resource ID of the API management service policy') +output resourceId string = policy.id + +@description('The name of the API management service policy') +output name string = policy.name + +@description('The resource group the API management service policy was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/policies/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/policies/readme.md new file mode 100644 index 000000000..b6cefab6c --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/policies/readme.md @@ -0,0 +1,31 @@ +# API Management Service Policies `[Microsoft.ApiManagement/service/policies]` + +This module deploys API Management Service Policy. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/policies` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `format` | string | `xml` | `[rawxml, rawxml-link, xml, xml-link]` | Optional. Format of the policyContent. | +| `name` | string | `policy` | | Optional. The name of the policy | +| `value` | string | | | Required. Contents of the Policy as defined by the format. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service policy | +| `resourceGroupName` | string | The resource group the API management service policy was deployed into | +| `resourceId` | string | The resource ID of the API management service policy | + +## Template references + +- [Service/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/policies) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/policies/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/policies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/policies/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/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/deploy.bicep new file mode 100644 index 000000000..63b3f8255 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/deploy.bicep @@ -0,0 +1,40 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Required. Portal setting name') +@allowed([ + 'delegation' + 'signin' + 'signup' +]) +param name string + +@description('Optional. Portal setting properties.') +param properties object = {} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource portalSetting 'Microsoft.ApiManagement/service/portalsettings@2021-08-01' = if (!empty(properties)) { + name: any(name) + parent: service + properties: properties +} + +@description('The resource ID of the API management service portal setting') +output resourceId string = portalSetting.id + +@description('The name of the API management service portal setting') +output name string = portalSetting.name + +@description('The resource group the API management service portal setting was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/readme.md new file mode 100644 index 000000000..912d8918b --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/readme.md @@ -0,0 +1,30 @@ +# API Management Service Portal Settings `[Microsoft.ApiManagement/service/portalsettings]` + +This module deploys API Management Service Portal Setting. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/portalsettings` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | `[delegation, signin, signup]` | Required. Portal setting name | +| `properties` | object | `{object}` | | Optional. Portal setting properties. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service portal setting | +| `resourceGroupName` | string | The resource group the API management service portal setting was deployed into | +| `resourceId` | string | The resource ID of the API management service portal setting | + +## Template references + +- ['service/portalsettings' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/service) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/portalsettings/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/carml/1.0.0/Microsoft.ApiManagement/service/products/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/products/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/deploy.bicep new file mode 100644 index 000000000..416285c15 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/deploy.bicep @@ -0,0 +1,38 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. The name of the of the Product.') +param productName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Required. Name of the product API.') +param name string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName + + resource product 'products@2021-04-01-preview' existing = { + name: productName + } +} + +resource api 'Microsoft.ApiManagement/service/products/apis@2021-08-01' = { + name: name + parent: service::product +} + +@description('The resource ID of the product API') +output resourceId string = api.id + +@description('The name of the product API') +output name string = api.name + +@description('The resource group the product API was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/readme.md new file mode 100644 index 000000000..ff50366e0 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/readme.md @@ -0,0 +1,30 @@ +# API Management Service Products APIs `[Microsoft.ApiManagement/service/products/apis]` + +This module deploys API Management Service Product APIs. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/products/apis` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Name of the product API. | +| `productName` | string | | | Required. The name of the of the Product. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the product API | +| `resourceGroupName` | string | The resource group the product API was deployed into | +| `resourceId` | string | The resource ID of the product API | + +## Template references + +- [Service/Products/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/apis) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/apis/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/carml/1.0.0/Microsoft.ApiManagement/service/products/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/products/deploy.bicep new file mode 100644 index 000000000..6c5fd141a --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/deploy.bicep @@ -0,0 +1,88 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Whether subscription approval is required. If false, new subscriptions will be approved automatically enabling developers to call the products APIs immediately after subscribing. If true, administrators must manually approve the subscription before the developer can any of the products APIs. Can be present only if subscriptionRequired property is present and has a value of false.') +param approvalRequired bool = false + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Product description. May include HTML formatting tags.') +param productDescription string = '' + +@description('Optional. Array of Product APIs.') +param apis array = [] + +@description('Optional. Array of Product Groups.') +param groups array = [] + +@description('Required. Product Name.') +param name string + +@description('Optional. whether product is published or not. Published products are discoverable by users of developer portal. Non published products are visible only to administrators. Default state of Product is notPublished. - notPublished or published') +param state string = 'published' + +@description('Optional. Whether a product subscription is required for accessing APIs included in this product. If true, the product is referred to as "protected" and a valid subscription key is required for a request to an API included in the product to succeed. If false, the product is referred to as "open" and requests to an API included in the product can be made without a subscription key. If property is omitted when creating a new product it\'s value is assumed to be true.') +param subscriptionRequired bool = false + +@description('Optional. Whether the number of subscriptions a user can have to this product at the same time. Set to null or omit to allow unlimited per user subscriptions. Can be present only if subscriptionRequired property is present and has a value of false.') +param subscriptionsLimit int = 1 + +@description('Optional. Product terms of use. Developers trying to subscribe to the product will be presented and required to accept these terms before they can complete the subscription process.') +param terms string = '' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource product 'Microsoft.ApiManagement/service/products@2021-08-01' = { + name: name + parent: service + properties: { + description: productDescription + displayName: name + terms: terms + subscriptionRequired: subscriptionRequired + approvalRequired: subscriptionRequired ? approvalRequired : null + subscriptionsLimit: subscriptionRequired ? subscriptionsLimit : null + state: state + } +} + +module product_apis 'apis/deploy.bicep' = [for (api, index) in apis: { + name: '${deployment().name}-Api-${index}' + params: { + apiManagementServiceName: apiManagementServiceName + name: api.name + productName: name + } +}] + +module product_groups 'groups/deploy.bicep' = [for (group, index) in groups: { + name: '${deployment().name}-Group-${index}' + params: { + apiManagementServiceName: apiManagementServiceName + name: group.name + productName: name + } +}] + +@description('The resource ID of the API management service product') +output resourceId string = product.id + +@description('The name of the API management service product') +output name string = product.name + +@description('The resource group the API management service product was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The Resources IDs of the API management service product APIs') +output apiResourceIds array = [for index in range(0, length(apis)): product_apis[index].outputs.resourceId] + +@description('The Resources IDs of the API management service product groups') +output groupResourceIds array = [for index in range(0, length(groups)): product_groups[index].outputs.resourceId] diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/deploy.bicep new file mode 100644 index 000000000..e65409637 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/deploy.bicep @@ -0,0 +1,38 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. The name of the of the Product.') +param productName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Required. Name of the product group.') +param name string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName + + resource product 'products@2021-04-01-preview' existing = { + name: productName + } +} + +resource group 'Microsoft.ApiManagement/service/products/groups@2021-08-01' = { + name: name + parent: service::product +} + +@description('The resource ID of the product group') +output resourceId string = group.id + +@description('The name of the product group') +output name string = group.name + +@description('The resource group the product group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/readme.md new file mode 100644 index 000000000..63ea7a723 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/readme.md @@ -0,0 +1,30 @@ +# API Management Service Products Groups `[Microsoft.ApiManagement/service/products/groups]` + +This module deploys API Management Service Product Groups. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/products/groups` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Name of the product group. | +| `productName` | string | | | Required. The name of the of the Product. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the product group | +| `resourceGroupName` | string | The resource group the product group was deployed into | +| `resourceId` | string | The resource ID of the product group | + +## Template references + +- [Service/Products/Groups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/groups) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/groups/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/carml/1.0.0/Microsoft.ApiManagement/service/products/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/products/readme.md new file mode 100644 index 000000000..9026f639f --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/readme.md @@ -0,0 +1,49 @@ +# API Management Service Products `[Microsoft.ApiManagement/service/products]` + +This module deploys API Management Service Products. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/products` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/groups` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `apis` | _[apis](apis/readme.md)_ array | `[]` | | Optional. Array of Product APIs. | +| `approvalRequired` | bool | | | Optional. Whether subscription approval is required. If false, new subscriptions will be approved automatically enabling developers to call the products APIs immediately after subscribing. If true, administrators must manually approve the subscription before the developer can any of the products APIs. Can be present only if subscriptionRequired property is present and has a value of false. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `groups` | _[groups](groups/readme.md)_ array | `[]` | | Optional. Array of Product Groups. | +| `name` | string | | | Required. Product Name. | +| `productDescription` | string | | | Optional. Product description. May include HTML formatting tags. | +| `state` | string | `published` | | Optional. whether product is published or not. Published products are discoverable by users of developer portal. Non published products are visible only to administrators. Default state of Product is notPublished. - notPublished or published | +| `subscriptionRequired` | bool | | | Optional. Whether a product subscription is required for accessing APIs included in this product. If true, the product is referred to as "protected" and a valid subscription key is required for a request to an API included in the product to succeed. If false, the product is referred to as "open" and requests to an API included in the product can be made without a subscription key. If property is omitted when creating a new product it's value is assumed to be true. | +| `subscriptionsLimit` | int | `1` | | Optional. Whether the number of subscriptions a user can have to this product at the same time. Set to null or omit to allow unlimited per user subscriptions. Can be present only if subscriptionRequired property is present and has a value of false. | +| `terms` | string | | | Optional. Product terms of use. Developers trying to subscribe to the product will be presented and required to accept these terms before they can complete the subscription process. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `apiResourceIds` | array | The Resources IDs of the API management service product APIs | +| `groupResourceIds` | array | The Resources IDs of the API management service product groups | +| `name` | string | The name of the API management service product | +| `resourceGroupName` | string | The resource group the API management service product was deployed into | +| `resourceId` | string | The resource ID of the API management service product | + +## Template references + +- [Service/Products](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products) +- [Service/Products/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/apis) +- [Service/Products/Groups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/groups) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/products/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/products/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/products/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/carml/1.0.0/Microsoft.ApiManagement/service/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/readme.md new file mode 100644 index 000000000..59b0616fa --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/readme.md @@ -0,0 +1,171 @@ +# API Management Services `[Microsoft.ApiManagement/service]` + +This module deploys an API management service. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apis/policies` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apiVersionSets` | 2021-08-01 | +| `Microsoft.ApiManagement/service/authorizationServers` | 2021-08-01 | +| `Microsoft.ApiManagement/service/backends` | 2021-08-01 | +| `Microsoft.ApiManagement/service/caches` | 2021-08-01 | +| `Microsoft.ApiManagement/service/identityProviders` | 2021-08-01 | +| `Microsoft.ApiManagement/service/namedValues` | 2021-08-01 | +| `Microsoft.ApiManagement/service/policies` | 2021-08-01 | +| `Microsoft.ApiManagement/service/portalsettings` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/groups` | 2021-08-01 | +| `Microsoft.ApiManagement/service/subscriptions` | 2021-08-01 | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalLocations` | array | `[]` | | Optional. Additional datacenter locations of the API Management service. | +| `apis` | _[apis](apis/readme.md)_ array | `[]` | | Optional. APIs. | +| `apiVersionSets` | _[apiVersionSets](apiVersionSets/readme.md)_ array | `[]` | | Optional. API Version Sets. | +| `authorizationServers` | _[authorizationServers](authorizationServers/readme.md)_ array | `[]` | | Optional. Authorization servers. | +| `backends` | _[backends](backends/readme.md)_ array | `[]` | | Optional. Backends. | +| `caches` | _[caches](caches/readme.md)_ array | `[]` | | Optional. Caches. | +| `certificates` | array | `[]` | | Optional. List of Certificates that need to be installed in the API Management service. Max supported certificates that can be installed is 10. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customProperties` | object | `{object}` | | Optional. Custom properties of the API Management service. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `disableGateway` | bool | | | Optional. Property only valid for an API Management service deployed in multiple locations. This can be used to disable the gateway in master region. | +| `enableClientCertificate` | bool | | | Optional. Property only meant to be used for Consumption SKU Service. This enforces a client certificate to be presented on each request to the gateway. This also enables the ability to authenticate the certificate in the policy on the gateway. | +| `hostnameConfigurations` | array | `[]` | | Optional. Custom hostname configuration of the API Management service. | +| `identityProviders` | _[identityProviders](identityProviders/readme.md)_ array | `[]` | | Optional. Identity providers. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[GatewayLogs]` | `[GatewayLogs]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `minApiVersion` | string | | | Optional. Limit control plane API calls to API Management service with version equal to or newer than this value. | +| `name` | string | | | Required. The name of the of the API Management service. | +| `namedValues` | _[namedValues](namedValues/readme.md)_ array | `[]` | | Optional. Named values. | +| `newGuidValue` | string | `[newGuid()]` | | Optional. Necessary to create a new GUID. | +| `notificationSenderEmail` | string | `apimgmt-noreply@mail.windowsazure.com` | | Optional. The notification sender email address for the service. | +| `policies` | _[policies](policies/readme.md)_ array | `[]` | | Optional. Policies. | +| `portalSettings` | _[portalSettings](portalSettings/readme.md)_ array | `[]` | | Optional. Portal settings. | +| `products` | _[products](products/readme.md)_ array | `[]` | | Optional. Products. | +| `publisherEmail` | string | | | Required. The email address of the owner of the service. | +| `publisherName` | string | | | Required. The name of the owner of the service. | +| `restore` | bool | | | Optional. Undelete API Management Service if it was previously soft-deleted. If this flag is specified and set to True all other properties will be ignored. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `Developer` | `[Consumption, Developer, Basic, Standard, Premium]` | Optional. The pricing tier of this API Management service. | +| `skuCount` | int | `1` | `[1, 2]` | Optional. The instance size of this API Management service. | +| `subnetResourceId` | string | | | Optional. The full resource ID of a subnet in a virtual network to deploy the API Management service in. | +| `subscriptions` | _[subscriptions](subscriptions/readme.md)_ array | `[]` | | Optional. Subscriptions. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `virtualNetworkType` | string | `None` | `[None, External, Internal]` | Optional. The type of VPN in which API Management service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only. | +| `zones` | array | `[]` | | Optional. A list of availability zones denoting where the resource needs to come from. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `apiManagementServicePolicy` + +```Json +"apiManagementServicePolicy": { + "value": { + "value":" ", + "format":"xml" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service | +| `resourceGroupName` | string | The resource group the API management service was deployed into | +| `resourceId` | string | The resource ID of the API management service | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +- *None* + +## Template references + +- ['service/portalsettings' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/service) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Service](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service) +- [Service/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis) +- [Service/Apis/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis/policies) +- [Service/Apiversionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apiVersionSets) +- [Service/Authorizationservers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/authorizationServers) +- [Service/Backends](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/backends) +- [Service/Caches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/caches) +- [Service/Identityproviders](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/identityProviders) +- [Service/Namedvalues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/namedValues) +- [Service/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/policies) +- [Service/Products](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products) +- [Service/Products/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/apis) +- [Service/Products/Groups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/groups) +- [Service/Subscriptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/subscriptions) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/deploy.bicep b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/deploy.bicep new file mode 100644 index 000000000..0c7d4cc81 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/deploy.bicep @@ -0,0 +1,58 @@ +@description('Optional. Determines whether tracing can be enabled.') +param allowTracing bool = true + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. User (user ID path) for whom subscription is being created in form /users/{userId}') +param ownerId string = '' + +@description('Optional. Primary subscription key. If not specified during request key will be generated automatically.') +param primaryKey string = '' + +@description('Optional. Scope type to choose between a product, "allAPIs" or a specific API. Scope like "/products/{productId}" or "/apis" or "/apis/{apiId}".') +param scope string = '/apis' + +@description('Optional. Secondary subscription key. If not specified during request key will be generated automatically.') +param secondaryKey string = '' + +@description('Optional. Initial subscription state. If no value is specified, subscription is created with Submitted state. Possible states are "*" active "?" the subscription is active, "*" suspended "?" the subscription is blocked, and the subscriber cannot call any APIs of the product, * submitted ? the subscription request has been made by the developer, but has not yet been approved or rejected, * rejected ? the subscription request has been denied by an administrator, * cancelled ? the subscription has been cancelled by the developer or administrator, * expired ? the subscription reached its expiration date and was deactivated. - suspended, active, expired, submitted, rejected, cancelled') +param state string = '' + +@description('Required. Subscription name.') +param name string + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource subscription 'Microsoft.ApiManagement/service/subscriptions@2021-08-01' = { + name: name + parent: service + properties: { + scope: scope + displayName: name + ownerId: !empty(ownerId) ? ownerId : null + primaryKey: !empty(primaryKey) ? primaryKey : null + secondaryKey: !empty(secondaryKey) ? secondaryKey : null + state: !empty(state) ? state : null + allowTracing: allowTracing + } +} + +@description('The resource ID of the API management service subscription') +output resourceId string = subscription.id + +@description('The name of the API management service subscription') +output name string = subscription.name + +@description('The resource group the API management service subscription was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/readme.md b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/readme.md new file mode 100644 index 000000000..9b3bd6414 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/readme.md @@ -0,0 +1,41 @@ +# API Management Subscriptions `[Microsoft.ApiManagement/service/subscriptions]` + +This module deploys API Management Subscriptions. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/subscriptions` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowTracing` | bool | `True` | | Optional. Determines whether tracing can be enabled. | +| `apiManagementServiceName` | string | | | Required. The name of the of the API Management service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Subscription name. | +| `ownerId` | string | | | Optional. User (user ID path) for whom subscription is being created in form /users/{userId} | +| `primaryKey` | string | | | Optional. Primary subscription key. If not specified during request key will be generated automatically. | +| `scope` | string | `/apis` | | Optional. Scope type to choose between a product, "allAPIs" or a specific API. Scope like "/products/{productId}" or "/apis" or "/apis/{apiId}". | +| `secondaryKey` | string | | | Optional. Secondary subscription key. If not specified during request key will be generated automatically. | +| `state` | string | | | Optional. Initial subscription state. If no value is specified, subscription is created with Submitted state. Possible states are "*" active "?" the subscription is active, "*" suspended "?" the subscription is blocked, and the subscriber cannot call any APIs of the product, * submitted ? the subscription request has been made by the developer, but has not yet been approved or rejected, * rejected ? the subscription request has been denied by an administrator, * cancelled ? the subscription has been cancelled by the developer or administrator, * expired ? the subscription reached its expiration date and was deactivated. - suspended, active, expired, submitted, rejected, cancelled | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service subscription | +| `resourceGroupName` | string | The resource group the API management service subscription was deployed into | +| `resourceId` | string | The resource ID of the API management service subscription | + +## Template references + +- [Service/Subscriptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/subscriptions) diff --git a/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/subscriptions/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/carml/1.0.0/Microsoft.ApiManagement/service/version.json b/carml/1.0.0/Microsoft.ApiManagement/service/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ApiManagement/service/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..7271e1d83 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json new file mode 100644 index 000000000..f140b8c7e --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..de4e5052a --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json new file mode 100644 index 000000000..e28b39cfd --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..ebadf2e43 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/sub.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": { + "name": { + "value": "<>-min-sub-polAss" + }, + "policyDefinitionID": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json new file mode 100644 index 000000000..cc671f092 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/.parameters/sub.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": "<>-sub-polAss" + }, + "displayName": { + "value": "[Display Name] Policy Assignment at the subscription scope" + }, + "description": { + "value": "[Description] Policy Assignment at the subscription 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" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policyAssignments/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyAssignments/deploy.bicep new file mode 100644 index 000000000..7e5c1b1e8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/deploy.bicep @@ -0,0 +1,124 @@ +targetScope = 'managementGroup' + +@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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment') +param subscriptionId string = '' + +@sys.description('Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment') +param resourceGroupName string = '' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +module policyAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + managementGroupId: managementGroupId + location: location + } +} + +module policyAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + subscriptionId: subscriptionId + location: location + } +} + +module policyAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + subscriptionId: subscriptionId + location: location + } +} + +@sys.description('Policy Assignment 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(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(subscriptionId) && empty(resourceGroupName) ? policyAssignment_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_sub.outputs.resourceId : policyAssignment_rg.outputs.resourceId) diff --git a/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep new file mode 100644 index 000000000..7cfbb7889 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep @@ -0,0 +1,92 @@ +targetScope = 'managementGroup' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +var nonComplianceMessage_var = { + message: !empty(nonComplianceMessage) ? nonComplianceMessage : null +} + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(managementGroupId, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@sys.description('Policy Assignment resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyAssignments', policyAssignment.name) diff --git a/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/readme.md new file mode 100644 index 000000000..1f527ccc1 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/version.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/readme.md b/carml/1.0.0/Microsoft.Authorization/policyAssignments/readme.md new file mode 100644 index 000000000..b7cc49035 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/readme.md @@ -0,0 +1,101 @@ +# 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 | +| :-- | :-- | +| `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, 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. | +| `policyDefinitionId` | string | | | Required. Specifies the ID of the policy definition or policy set definition being assigned. | +| `resourceGroupName` | string | | | Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment | +| `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 | | | Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment | + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `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/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep new file mode 100644 index 000000000..c6e25feff --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep @@ -0,0 +1,106 @@ +targetScope = 'resourceGroup' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +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. 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. 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 + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(subscriptionId, resourceGroupName, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@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/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md new file mode 100644 index 000000000..57000e661 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/version.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep new file mode 100644 index 000000000..d13fbf2e8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep @@ -0,0 +1,92 @@ +targetScope = 'subscription' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +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. If not provided, will use the current scope for deployment.') +param subscriptionId string = subscription().subscriptionId + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(subscriptionId, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@sys.description('Policy Assignment resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyAssignments', policyAssignment.name) diff --git a/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/readme.md b/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/readme.md new file mode 100644 index 000000000..0214edc0c --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/version.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyAssignments/version.json b/carml/1.0.0/Microsoft.Authorization/policyAssignments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyAssignments/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..431a0f6f5 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..7196de615 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..f2cd03cfb --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-sub-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" + } + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..e44512751 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.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": "<>-sub-policyDef" + }, + "displayName": { + "value": "[DisplayName] This policy definition is deployed at subscription scope" + }, + "description": { + "value": "[Description] This policy definition is deployed at subscription 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" + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policyDefinitions/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/deploy.bicep new file mode 100644 index 000000000..198a9be60 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/deploy.bicep @@ -0,0 +1,79 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +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). 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 = '' + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +module policyDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + managementGroupId: managementGroupId + mode: mode + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyRule: policyRule + } +} + +module policyDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + subscriptionId: subscriptionId + mode: mode + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = empty(subscriptionId) ? policyDefinition_mg.outputs.name : policyDefinition_sub.outputs.name + +@sys.description('Policy Definition resource ID') +output resourceId string = empty(subscriptionId) ? policyDefinition_mg.outputs.resourceId : policyDefinition_sub.outputs.resourceId + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = empty(subscriptionId) ? policyDefinition_mg.outputs.roleDefinitionIds : policyDefinition_sub.outputs.roleDefinitionIds diff --git a/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..2e0046ff2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,56 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +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. 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 + properties: { + policyType: 'Custom' + mode: mode + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = policyDefinition.name + +@sys.description('Policy Definition resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyDefinitions', policyDefinition.name) + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = (contains(policyDefinition.properties.policyRule.then, 'details') ? ((contains(policyDefinition.properties.policyRule.then.details, 'roleDefinitionIds') ? policyDefinition.properties.policyRule.then.details.roleDefinitionIds : [])) : []) diff --git a/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..ba5d7fe80 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/version.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/readme.md b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/readme.md new file mode 100644 index 000000000..5190891a5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/readme.md @@ -0,0 +1,79 @@ +# 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 | +| :-- | :-- | +| `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. | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `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. 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 | + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +## 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 | +| :-- | :-- | :-- | +| `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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..b99c23225 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep @@ -0,0 +1,56 @@ +targetScope = 'subscription' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Required. The Policy Rule details for the Policy Definition') +param policyRule object + +@sys.description('Optional. The subscription ID of the subscription') +param subscriptionId string = subscription().subscriptionId + +resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + mode: mode + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = policyDefinition.name + +@sys.description('Policy Definition resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyDefinitions', policyDefinition.name) + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = (contains(policyDefinition.properties.policyRule.then, 'details') ? ((contains(policyDefinition.properties.policyRule.then.details, 'roleDefinitionIds') ? policyDefinition.properties.policyRule.then.details.roleDefinitionIds : [])) : []) diff --git a/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/readme.md b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/readme.md new file mode 100644 index 000000000..4f47add45 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/version.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyDefinitions/version.json b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyDefinitions/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..f5816fcd6 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json new file mode 100644 index 000000000..2c76ecb64 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..2573b17fe --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json new file mode 100644 index 000000000..68fda77de --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..920e7d2ad --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/sub.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": { + "name": { + "value": "<>-min-sub-polexem" + }, + "policyAssignmentId": { + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json new file mode 100644 index 000000000..02b3e9037 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/.parameters/sub.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": "<>-sub-polexem" + }, + "displayName": { + "value": "[Display Name] policy exempt (subscription 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": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyExemptions/deploy.bicep new file mode 100644 index 000000000..5f89ad16f --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/deploy.bicep @@ -0,0 +1,101 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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 = '' + +@sys.description('Optional. The name of the resource group to be exempted from the policy assignment. Must also use the subscription ID parameter.') +param resourceGroupName string = '' + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +module policyExemption_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + managementGroupId: managementGroupId + } +} + +module policyExemption_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + subscriptionId: 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: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + } +} + +@sys.description('Policy Exemption 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(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(subscriptionId) && empty(resourceGroupName) ? policyExemption_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_sub.outputs.scope : policyExemption_rg.outputs.scope) diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep new file mode 100644 index 000000000..c1f1169e9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep @@ -0,0 +1,56 @@ +targetScope = 'managementGroup' + +@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 assignment. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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 + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@sys.description('Policy Exemption Scope') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/readme.md new file mode 100644 index 000000000..3ac457016 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/version.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/readme.md b/carml/1.0.0/Microsoft.Authorization/policyExemptions/readme.md new file mode 100644 index 000000000..6936706c5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/readme.md @@ -0,0 +1,100 @@ +# 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 | +| :-- | :-- | +| `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 | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `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, 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. | +| `subscriptionId` | string | | | Optional. The subscription ID of the subscription to be exempted from the policy assignment. Cannot use with management group ID parameter. | + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | Policy Exemption Name | +| `resourceId` | string | Policy Exemption resource ID | +| `scope` | string | Policy Exemption Scope | + +## Considerations + +- Policy Exemptions have a dependency on Policy Assignments being applied before creating an exemption. You can use the Policy Assignment [Module](../policyAssignments/deploy.bicep) to deploy a Policy Assignment and then create the exemption for it on the required scope. + +## Template references + +- [Policyexemptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-07-01-preview/policyExemptions) diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep new file mode 100644 index 000000000..22caa4f38 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep @@ -0,0 +1,70 @@ +targetScope = 'resourceGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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. 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: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = az.resourceId(subscriptionId, resourceGroupName, 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@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/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md new file mode 100644 index 000000000..57fedef4e --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/version.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep new file mode 100644 index 000000000..9d8678ebb --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep @@ -0,0 +1,56 @@ +targetScope = 'subscription' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. If not provided, will use the current scope for deployment.') +param subscriptionId string = subscription().subscriptionId + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@sys.description('Policy Exemption Scope') +output scope string = subscription().id diff --git a/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/readme.md b/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/readme.md new file mode 100644 index 000000000..111d44783 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/version.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policyExemptions/version.json b/carml/1.0.0/Microsoft.Authorization/policyExemptions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policyExemptions/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..92f9d4ac2 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..029e2d47c --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..f6a7e68f6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-sub-min-policySet" + }, + "policyDefinitions": { + "value": [ + { + "parameters": { + "listOfAllowedLocations": { + "value": [ + "australiaeast" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c" + } + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..16a92428b --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.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": "<>-sub-policySet" + }, + "displayName": { + "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": [ + { + "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" + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/deploy.bicep new file mode 100644 index 000000000..7aef6f525 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/deploy.bicep @@ -0,0 +1,69 @@ +targetScope = 'managementGroup' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@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). 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 = '' + +@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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +module policySetDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + managementGroupId: managementGroupId + } +} + +module policySetDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + subscriptionId: subscriptionId + } +} + +@sys.description('Policy Set Definition 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(subscriptionId) ? policySetDefinition_mg.outputs.resourceId : policySetDefinition_sub.outputs.resourceId diff --git a/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..192012e44 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,46 @@ +targetScope = 'managementGroup' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description name of the Set Definition (Initiative)') +param description 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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +resource policySetDefinition 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + } +} + +@sys.description('Policy Set Definition Name') +output name string = policySetDefinition.name + +@sys.description('Policy Set Definition resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policySetDefinitions', policySetDefinition.name) diff --git a/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..17ed1856b --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/readme.md b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/readme.md new file mode 100644 index 000000000..f2f27209c --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/readme.md @@ -0,0 +1,82 @@ +# 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 | +| :-- | :-- | +| `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. | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `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). 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 | +| `subscriptionId` | string | | | Optional. The subscription ID of the subscription (Scope). Cannot be used with managementGroupId | + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +## 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 | +| :-- | :-- | :-- | +| `name` | string | Policy Set Definition Name | +| `resourceId` | string | Policy Set Definition resource ID | + +## Considerations + +- Policy Set Definitions (Initiatives) have a dependency on Policy Assignments being applied before creating an initiative. You can use the Policy Assignment [Module](../policyDefinitions/deploy.bicep) to deploy a Policy Definition and then create an initiative for it on the required scope. + +## Template references + +- [Policysetdefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policySetDefinitions) diff --git a/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..236bc90c5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep @@ -0,0 +1,46 @@ +targetScope = 'subscription' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description name of the Set Definition (Initiative)') +param description string = '' + +@sys.description('Optional. The subscription ID of the subscription') +param subscriptionId string = subscription().subscriptionId + +@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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +resource policySetDefinition 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + } +} + +@sys.description('Policy Set Definition Name') +output name string = policySetDefinition.name + +@sys.description('Policy Set Definition resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policySetDefinitions', policySetDefinition.name) diff --git a/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/readme.md b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/readme.md new file mode 100644 index 000000000..11a83a542 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/version.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/version.json b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/policySetDefinitions/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..02a409875 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json new file mode 100644 index 000000000..e6362b62a --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..6011dc7e9 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json new file mode 100644 index 000000000..faf9fc3d9 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..2a90f97fb --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/sub.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": { + "roleDefinitionIdOrName": { + "value": "Storage Queue Data Reader" + }, + "principalId": { + "value": "<>" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json new file mode 100644 index 000000000..346ba64c0 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/.parameters/sub.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 (subscription scope)" + }, + "principalId": { + "value": "<>" + }, + "principalType": { + "value": "ServicePrincipal" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleAssignments/deploy.bicep new file mode 100644 index 000000000..01a069ea8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/deploy.bicep @@ -0,0 +1,100 @@ +targetScope = 'managementGroup' + +@sys.description('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\'') +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 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 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 + +@sys.description('Optional. Description of role assignment') +param description string = '' + +@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') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +module roleAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-MG-Module' + scope: managementGroup(managementGroupId) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + managementGroupId: managementGroupId + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + } +} + +module roleAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-Sub-Module' + scope: subscription(subscriptionId) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + subscriptionId: subscriptionId + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + } +} + +module roleAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + } +} + +@sys.description('The GUID of the Role Assignment') +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(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(subscriptionId) && empty(resourceGroupName) ? roleAssignment_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_sub.outputs.scope : roleAssignment_rg.outputs.scope) diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep new file mode 100644 index 000000000..1bc2e4ce8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep @@ -0,0 +1,344 @@ +targetScope = 'managementGroup' + +@sys.description('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\'') +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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType 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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(managementGroupId, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) + +@sys.description('The scope this Role Assignment applies to') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/roleAssignments', roleAssignment.name) diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/readme.md new file mode 100644 index 000000000..10e98eb01 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/version.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/readme.md b/carml/1.0.0/Microsoft.Authorization/roleAssignments/readme.md new file mode 100644 index 000000000..bbfb50fcc --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/readme.md @@ -0,0 +1,99 @@ +# Role Assignments `[Microsoft.Authorization/roleAssignments]` + +This module deploys Role Assignments across the management group, subscription or resource group scope. + +## 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 | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `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 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. | + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Assignment | +| `resourceId` | string | The resource ID of the Role Assignment | +| `scope` | string | The scope this Role Assignment applies to | + +## Considerations + +This module can be deployed at the management group, subscription or resource group level + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep new file mode 100644 index 000000000..693661c13 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep @@ -0,0 +1,358 @@ +targetScope = 'resourceGroup' + +@sys.description('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\'') +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 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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +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: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +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/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md new file mode 100644 index 000000000..aca00e1a3 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/version.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep new file mode 100644 index 000000000..bf5f0fcd9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep @@ -0,0 +1,344 @@ +targetScope = 'subscription' + +@sys.description('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\'') +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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType 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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(subscriptionId, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +output scope string = subscription().id + +@sys.description('The scope this Role Assignment applies to') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/roleAssignments', roleAssignment.name) diff --git a/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/readme.md b/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/readme.md new file mode 100644 index 000000000..54917e335 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/version.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleAssignments/version.json b/carml/1.0.0/Microsoft.Authorization/roleAssignments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleAssignments/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..c4a88ba9e --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..d49ce1cae --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..cf6825cc0 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json new file mode 100644 index 000000000..c27ff2f86 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..87bbbc20b --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.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": { + "roleName": { + "value": "<>-az-testRole-sub-min" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..62e03ca98 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.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-sub" + }, + "description": { + "value": "Test Custom Role Definition Standard (subscription 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/<>" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/deploy.bicep new file mode 100644 index 000000000..2fed913ce --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/deploy.bicep @@ -0,0 +1,87 @@ +targetScope = 'managementGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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 = '' + +@sys.description('Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to.') +param resourceGroupName string = '' + +@sys.description('Optional. Location for all resources.') +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 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + managementGroupId: managementGroupId + } +} + +module roleDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + dataActions: !empty(dataActions) ? dataActions : [] + notDataActions: !empty(notDataActions) ? notDataActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + subscriptionId: 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: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + dataActions: !empty(dataActions) ? dataActions : [] + notDataActions: !empty(notDataActions) ? notDataActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + } +} + +@sys.description('The GUID of the Role Definition') +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(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(subscriptionId) && empty(resourceGroupName) ? roleDefinition_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_sub.outputs.scope : roleDefinition_rg.outputs.scope) diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..b915817aa --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,44 @@ +targetScope = 'managementGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@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 = [] + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, managementGroupId) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + } + ] + assignableScopes: assignableScopes == [] ? array(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId)) : assignableScopes + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) + +@sys.description('The resource ID of the Role Definition') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/roleDefinitions', roleDefinition.name) diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..50dc65f01 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/version.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/readme.md b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/readme.md new file mode 100644 index 000000000..5df05a832 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/readme.md @@ -0,0 +1,103 @@ +# Role Definitions `[Microsoft.Authorization/roleDefinitions]` + +This module deploys custom RBAC Role Definitions across the management group, subscription or resource group scope. + +## 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. | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `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. | +| `roleName` | string | | | Required. Name of the custom RBAC role to be created. | +| `subscriptionId` | string | | | Optional. The subscription ID where the Role Definition and Target Scope will be applied to. Use for both Subscription level and Resource Group Level. | + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Definition | +| `resourceId` | string | The resource ID of the Role Definition | +| `roleDefinitionScope` | string | The scope this Role Definition applies to | + +## Considerations + +This module can be deployed both at subscription or resource group level: + +- To deploy the module at resource group level, provide a valid name of an existing Resource Group in the `resourceGroupName` parameter and an existing subscription ID in the `subscriptionId` parameter. +- To deploy the module at the subscription level, provide an existing subscription ID in the `subscriptionId` parameter. +- To deploy the module at the management group level, provide an existing management group ID in the `managementGroupId` parameter. + +## Template references + +- [Roledefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2018-01-01-preview/roleDefinitions) diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep new file mode 100644 index 000000000..d55962d78 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep @@ -0,0 +1,66 @@ +targetScope = 'resourceGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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. 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: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + dataActions: dataActions + notDataActions: notDataActions + } + ] + assignableScopes: assignableScopes == [] ? array(resourceGroup().id) : assignableScopes + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md new file mode 100644 index 000000000..f42b3bab2 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..abc70bc7f --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep @@ -0,0 +1,52 @@ +targetScope = 'subscription' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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.') +param assignableScopes array = [] + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, subscriptionId) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + dataActions: dataActions + notDataActions: notDataActions + } + ] + assignableScopes: !empty(assignableScopes) ? assignableScopes : array(subscription().id) + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +output scope string = subscription().id + +@sys.description('The resource ID of the Role Definition') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/roleDefinitions', roleDefinition.name) diff --git a/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/readme.md b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/readme.md new file mode 100644 index 000000000..950830c0c --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/version.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/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/carml/1.0.0/Microsoft.Authorization/roleDefinitions/version.json b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Authorization/roleDefinitions/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/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_linkedService.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_linkedService.bicep new file mode 100644 index 000000000..a5db7f142 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_linkedService.bicep @@ -0,0 +1,37 @@ +@description('Required. Name of the link') +param name string + +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access.') +param resourceId string = '' + +@description('Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access. ') +param writeAccessResourceId string = '' + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource linkedService 'Microsoft.OperationalInsights/workspaces/linkedServices@2020-03-01-preview' = { + name: name + parent: logAnalyticsWorkspace + tags: tags + properties: { + resourceId: !empty(resourceId) ? resourceId : null + writeAccessResourceId: !empty(writeAccessResourceId) ? writeAccessResourceId : null + } +} + +@description('The name of the deployed linked service') +output name string = linkedService.name + +@description('The resource ID of the deployed linked service') +output resourceId string = linkedService.id + +@description('The resource group where the linked service is deployed') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..26e201e43 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..777f9d3bd --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') + 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') + 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(automationAccount.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: automationAccount +}] diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_solution.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_solution.bicep new file mode 100644 index 000000000..b6cbf586e --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.bicep/nested_solution.bicep @@ -0,0 +1,43 @@ +@description('Required. Name of the solution') +param name string + +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The product of the deployed solution. For gallery solution, it is OMSGallery.') +param product string = 'OMSGallery' + +@description('Optional. The publisher name of the deployed solution. For gallery solution, it is Microsoft.') +param publisher string = 'Microsoft' + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { + name: logAnalyticsWorkspaceName +} + +var solutionName = '${name}(${logAnalyticsWorkspace.name})' + +resource solution 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { + name: solutionName + location: location + properties: { + workspaceResourceId: logAnalyticsWorkspace.id + } + plan: { + name: solutionName + promotionCode: '' + product: '${product}/${name}' + publisher: publisher + } +} + +@description('The name of the deployed solution') +output name string = solution.name + +@description('The resource ID of the deployed solution') +output resourceId string = solution.id + +@description('The resource group where the solution is deployed') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..36d11228d --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-wd-aut-min-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/.parameters/parameters.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/.parameters/parameters.json new file mode 100644 index 000000000..d95589e97 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/.parameters/parameters.json @@ -0,0 +1,192 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-wd-aut-x-001" + }, + "schedules": { + "value": [ + { + "name": "TestSchedule", + "startTime": "", + "expiryTime": "9999-12-31T23:59:00+00:00", + "interval": 15, + "frequency": "Minute", + "timeZone": "Europe/Berlin", + "advancedSchedule": {} + } + ] + }, + "modules": { + "value": [ + { + "name": "PSWindowsUpdate", + "version": "latest", + "uri": "https://www.powershellgallery.com/api/v2/package" + } + ] + }, + "runbooks": { + "value": [ + { + "name": "TestRunbook", + "runbookType": "PowerShell", + "description": "Test runbook", + "uri": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1", + "version": "1.0.0.0" + } + ] + }, + "jobSchedules": { + "value": [ + { + "scheduleName": "TestSchedule", + "runbookName": "TestRunbook" + } + ] + }, + "variables": { + "value": [ + { + "name": "TestString", + "value": "\"TestString\"", + "description": "TestStringDescription" + }, + { + "name": "TestInteger", + "value": "500", + "description": "TestIntegerDescription" + }, + { + "name": "TestBoolean", + "value": "false", + "description": "TestBooleanDescription" + }, + { + "name": "TestDateTime", + "value": "\"\\/Date(1637934042656)\\/\"", + "description": "TestDateTimeDescription" + }, + { + "name": "TestEncryptedVariable", + "value": "\"TestEncryptedValue\"", + "description": "TestEncryptedDescription", + "isEncrypted": true + } + ] + }, + "linkedWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "gallerySolutions": { + "value": [ + "Updates" + ] + }, + "softwareUpdateConfigurations": { + "value": [ + { + "name": "Windows_ZeroDay", + "frequency": "Month", + "operatingSystem": "Windows", + "rebootSetting": "IfRequired", + "scopeByTags": { + "Update": [ + "Automatic-Wave1" + ] + }, + "maintenanceWindow": "PT4H", + "updateClassifications": [ + "Critical", + "Security", + "UpdateRollup", + "FeaturePack", + "ServicePack", + "Definition", + "Tools", + "Updates" + ], + "includeUpdates": [ + "654321" + ], + "excludeUpdates": [ + "123456" + ], + "interval": 1, + "monthlyOccurrences": [ + { + "occurrence": 3, + "day": "Friday" + } + ], + "startTime": "22:00" + }, + { + "name": "Linux_ZeroDay", + "frequency": "OneTime", + "operatingSystem": "Linux", + "rebootSetting": "IfRequired", + "maintenanceWindow": "PT4H", + "updateClassifications": [ + "Critical", + "Security", + "Other" + ], + "includeUpdates": [ + "kernel" + ], + "excludeUpdates": [ + "icacls" + ], + "startTime": "22:00" + } + ] + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "Webhook" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "DSCAndHybridWorker" + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/deploy.bicep new file mode 100644 index 000000000..b1caa69c5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/deploy.bicep @@ -0,0 +1,336 @@ +@description('Required. Name of the Automation Account.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'Free' + 'Basic' +]) +@description('Optional. SKU name of the account.') +param skuName string = 'Basic' + +@description('Optional. List of modules to be created in the automation account.') +param modules array = [] + +@description('Optional. List of runbooks to be created in the automation account.') +param runbooks array = [] + +@description('Optional. List of schedules to be created in the automation account.') +param schedules array = [] + +@description('Optional. List of jobSchedules to be created in the automation account.') +param jobSchedules array = [] + +@description('Optional. List of variables to be created in the automation account.') +param variables array = [] + +@description('Optional. ID of the log analytics workspace to be linked to the deployed automation account.') +param linkedWorkspaceId string = '' + +@description('Optional. List of gallerySolutions to be created in the linked log analytics workspace') +param gallerySolutions array = [] + +@description('Optional. List of softwareUpdateConfigurations to be created in the automation account') +param softwareUpdateConfigurations array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@minValue(0) +@maxValue(365) +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the Automation Account resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'JobLogs' + 'JobStreams' + 'DscNodeStatus' +]) +param logsToEnable array = [ + 'JobLogs' + 'JobStreams' + 'DscNodeStatus' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' = { + name: name + location: location + tags: tags + properties: { + sku: { + name: skuName + } + } + identity: identity +} + +module automationAccount_modules 'modules/deploy.bicep' = [for (module, index) in modules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Module-${index}' + params: { + name: module.name + automationAccountName: automationAccount.name + version: module.version + uri: module.uri + location: location + tags: tags + } +}] + +module automationAccount_schedules 'schedules/deploy.bicep' = [for (schedule, index) in schedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Schedule-${index}' + params: { + name: schedule.name + automationAccountName: automationAccount.name + advancedSchedule: contains(schedule, 'advancedSchedule') ? schedule.advancedSchedule : null + scheduleDescription: contains(schedule, 'description') ? schedule.description : '' + expiryTime: contains(schedule, 'expiryTime') ? schedule.expiryTime : '' + frequency: contains(schedule, 'frequency') ? schedule.frequency : 'OneTime' + interval: contains(schedule, 'interval') ? schedule.interval : 0 + startTime: contains(schedule, 'startTime') ? schedule.startTime : '' + timeZone: contains(schedule, 'timeZone') ? schedule.timeZone : '' + } +}] + +module automationAccount_runbooks 'runbooks/deploy.bicep' = [for (runbook, index) in runbooks: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Runbook-${index}' + params: { + name: runbook.name + automationAccountName: automationAccount.name + runbookType: runbook.runbookType + runbookDescription: contains(runbook, 'description') ? runbook.description : '' + uri: contains(runbook, 'uri') ? runbook.uri : '' + version: contains(runbook, 'version') ? runbook.version : '' + location: location + tags: tags + } +}] + +module automationAccount_jobSchedules 'jobSchedules/deploy.bicep' = [for (jobSchedule, index) in jobSchedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-JobSchedule-${index}' + params: { + automationAccountName: automationAccount.name + runbookName: jobSchedule.runbookName + scheduleName: jobSchedule.scheduleName + parameters: contains(jobSchedule, 'parameters') ? jobSchedule.parameters : {} + runOn: contains(jobSchedule, 'runOn') ? jobSchedule.runOn : '' + } + dependsOn: [ + automationAccount_schedules + automationAccount_runbooks + ] +}] + +module automationAccount_variables 'variables/deploy.bicep' = [for (variable, index) in variables: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Variable-${index}' + params: { + automationAccountName: automationAccount.name + name: variable.name + description: contains(variable, 'description') ? variable.description : '' + value: variable.value + isEncrypted: contains(variable, 'isEncrypted') ? variable.isEncrypted : false + } +}] + +module automationAccount_linkedService '.bicep/nested_linkedService.bicep' = if (!empty(linkedWorkspaceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-LinkedService' + params: { + name: 'automation' + logAnalyticsWorkspaceName: last(split(linkedWorkspaceId, '/')) + resourceId: automationAccount.id + tags: tags + } + // This is to support linked services to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup(!empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[2] : subscription().subscriptionId, !empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[4] : resourceGroup().name) +} + +module automationAccount_solutions '.bicep/nested_solution.bicep' = [for (gallerySolution, index) in gallerySolutions: if (!empty(linkedWorkspaceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Solution-${index}' + params: { + name: gallerySolution + location: location + logAnalyticsWorkspaceName: last(split(linkedWorkspaceId, '/')) + } + // This is to support solution to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup(!empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[2] : subscription().subscriptionId, !empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[4] : resourceGroup().name) + dependsOn: [ + automationAccount_linkedService + ] +}] + +module automationAccount_softwareUpdateConfigurations 'softwareUpdateConfigurations/deploy.bicep' = [for (softwareUpdateConfiguration, index) in softwareUpdateConfigurations: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-SwUpdateConfig-${index}' + params: { + name: softwareUpdateConfiguration.name + automationAccountName: automationAccount.name + frequency: softwareUpdateConfiguration.frequency + operatingSystem: softwareUpdateConfiguration.operatingSystem + rebootSetting: softwareUpdateConfiguration.rebootSetting + azureVirtualMachines: contains(softwareUpdateConfiguration, 'azureVirtualMachines') ? softwareUpdateConfiguration.azureVirtualMachines : [] + excludeUpdates: contains(softwareUpdateConfiguration, 'excludeUpdates') ? softwareUpdateConfiguration.excludeUpdates : [] + expiryTime: contains(softwareUpdateConfiguration, 'expiryTime') ? softwareUpdateConfiguration.expiryTime : '' + expiryTimeOffsetMinutes: contains(softwareUpdateConfiguration, 'expiryTimeOffsetMinutes') ? softwareUpdateConfiguration.expiryTimeOffsetMinute : 0 + includeUpdates: contains(softwareUpdateConfiguration, 'includeUpdates') ? softwareUpdateConfiguration.includeUpdates : [] + interval: contains(softwareUpdateConfiguration, 'interval') ? softwareUpdateConfiguration.interval : 1 + isEnabled: contains(softwareUpdateConfiguration, 'isEnabled') ? softwareUpdateConfiguration.isEnabled : true + maintenanceWindow: contains(softwareUpdateConfiguration, 'maintenanceWindow') ? softwareUpdateConfiguration.maintenanceWindow : 'PT2H' + monthDays: contains(softwareUpdateConfiguration, 'monthDays') ? softwareUpdateConfiguration.monthDays : [] + monthlyOccurrences: contains(softwareUpdateConfiguration, 'monthlyOccurrences') ? softwareUpdateConfiguration.monthlyOccurrences : [] + nextRun: contains(softwareUpdateConfiguration, 'nextRun') ? softwareUpdateConfiguration.nextRun : '' + nextRunOffsetMinutes: contains(softwareUpdateConfiguration, 'nextRunOffsetMinutes') ? softwareUpdateConfiguration.nextRunOffsetMinutes : 0 + nonAzureComputerNames: contains(softwareUpdateConfiguration, 'nonAzureComputerNames') ? softwareUpdateConfiguration.nonAzureComputerNames : [] + nonAzureQueries: contains(softwareUpdateConfiguration, 'nonAzureQueries') ? softwareUpdateConfiguration.nonAzureQueries : [] + postTaskParameters: contains(softwareUpdateConfiguration, 'postTaskParameters') ? softwareUpdateConfiguration.postTaskParameters : {} + postTaskSource: contains(softwareUpdateConfiguration, 'postTaskSource') ? softwareUpdateConfiguration.postTaskSource : '' + preTaskParameters: contains(softwareUpdateConfiguration, 'preTaskParameters') ? softwareUpdateConfiguration.preTaskParameters : {} + preTaskSource: contains(softwareUpdateConfiguration, 'preTaskSource') ? softwareUpdateConfiguration.preTaskSource : '' + scheduleDescription: contains(softwareUpdateConfiguration, 'scheduleDescription') ? softwareUpdateConfiguration.scheduleDescription : '' + scopeByLocations: contains(softwareUpdateConfiguration, 'scopeByLocations') ? softwareUpdateConfiguration.scopeByLocations : [] + scopeByResources: contains(softwareUpdateConfiguration, 'scopeByResources') ? softwareUpdateConfiguration.scopeByResources : [ + subscription().id + ] + scopeByTags: contains(softwareUpdateConfiguration, 'scopeByTags') ? softwareUpdateConfiguration.scopeByTags : {} + scopeByTagsOperation: contains(softwareUpdateConfiguration, 'scopeByTagsOperation') ? softwareUpdateConfiguration.scopeByTagsOperation : 'All' + startTime: contains(softwareUpdateConfiguration, 'startTime') ? softwareUpdateConfiguration.startTime : '' + timeZone: contains(softwareUpdateConfiguration, 'timeZone') ? softwareUpdateConfiguration.timeZone : 'UTC' + updateClassifications: contains(softwareUpdateConfiguration, 'updateClassifications') ? softwareUpdateConfiguration.updateClassifications : [ + 'Critical' + 'Security' + ] + weekDays: contains(softwareUpdateConfiguration, 'weekDays') ? softwareUpdateConfiguration.weekDays : [] + } + dependsOn: [ + automationAccount_solutions + ] +}] + +resource automationAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${automationAccount.name}-AutoAccount-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: automationAccount +} + +resource automationAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${automationAccount.name}-AutoAccount-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: automationAccount +} + +module automationAccount_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: automationAccount.id + privateEndpointVnetLocation: !empty(privateEndpoints) ? reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location : 'dummy' + privateEndpointObj: endpoint + tags: tags + } +}] + +module automationAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: automationAccount.id + } +}] + +@description('The name of the deployed automation account') +output name string = automationAccount.name + +@description('The resource ID of the deployed automation account') +output resourceId string = automationAccount.id + +@description('The resource group of the deployed automation account') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(automationAccount.identity, 'principalId') ? automationAccount.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/deploy.bicep new file mode 100644 index 000000000..f21d47cd9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/deploy.bicep @@ -0,0 +1,53 @@ +@description('Optional. Name of the Automation Account job schedule. Must be a GUID. If not provided, a new GUID is generated.') +param name string = newGuid() + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@description('Required. The runbook property associated with the entity.') +param runbookName string + +@description('Required. The schedule property associated with the entity.') +param scheduleName string + +@description('Optional. List of job properties.') +param parameters object = {} + +@description('Optional. The hybrid worker group that the scheduled job should run on.') +param runOn string = '' + +@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 automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource jobSchedule 'Microsoft.Automation/automationAccounts/jobSchedules@2020-01-13-preview' = { + name: name + parent: automationAccount + properties: { + parameters: parameters + runbook: { + name: runbookName + } + runOn: !empty(runOn) ? runOn : null + schedule: { + name: scheduleName + } + } +} + +@description('The name of the deployed job schedule') +output name string = jobSchedule.name + +@description('The resource ID of the deployed job schedule') +output resourceId string = jobSchedule.id + +@description('The resource group of the deployed job schedule') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/readme.md new file mode 100644 index 000000000..6299676c1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/readme.md @@ -0,0 +1,33 @@ +# Automation Account Job Schedules `[Microsoft.Automation/automationAccounts/jobSchedules]` + +This module deploys an Azure Automation Account Job Schedule. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/jobSchedules` | 2020-01-13-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | | Required. Name of the parent Automation Account. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `name` | string | `[newGuid()]` | | Optional. Name of the Automation Account job schedule. Must be a GUID. If not provided, a new GUID is generated. | +| `parameters` | object | `{object}` | | Optional. List of job properties. | +| `runbookName` | string | | | Required. The runbook property associated with the entity. | +| `runOn` | string | | | Optional. The hybrid worker group that the scheduled job should run on. | +| `scheduleName` | string | | | Required. The schedule property associated with the entity. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed job schedule | +| `resourceGroupName` | string | The resource group of the deployed job schedule | +| `resourceId` | string | The resource ID of the deployed job schedule | + +## Template references + +- [Automationaccounts/Jobschedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/jobSchedules) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/jobSchedules/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/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/deploy.bicep new file mode 100644 index 000000000..429f29d1a --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. Name of the Automation Account module.') +param name string + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@description('Required. Module package uri, e.g. https://www.powershellgallery.com/api/v2/package.') +param uri string + +@description('Optional. Module version or specify latest to get the latest version.') +param version string = 'latest' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Automation Account resource.') +param tags object = {} + +@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 automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource module 'Microsoft.Automation/automationAccounts/modules@2020-01-13-preview' = { + name: name + parent: automationAccount + location: location + tags: tags + properties: { + contentLink: { + uri: version != 'latest' ? '${uri}/${name}/${version}' : '${uri}/${name}' + version: version != 'latest' ? version : null + } + } +} + +@description('The name of the deployed module') +output name string = module.name + +@description('The resource ID of the deployed module') +output resourceId string = module.id + +@description('The resource group of the deployed module') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/readme.md new file mode 100644 index 000000000..23a712f1f --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/readme.md @@ -0,0 +1,50 @@ +# Automation Account Modules `[Microsoft.Automation/automationAccounts/modules]` + +This module deploys an Azure Automation Account Module. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/modules` | 2020-01-13-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | | Required. Name of the parent Automation Account. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | | | Required. Name of the Automation Account module. | +| `tags` | object | `{object}` | | Optional. Tags of the Automation Account resource. | +| `uri` | string | | | Required. Module package uri, e.g. https://www.powershellgallery.com/api/v2/package. | +| `version` | string | `latest` | | Optional. Module version or specify latest to get the latest version. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed module | +| `resourceGroupName` | string | The resource group of the deployed module | +| `resourceId` | string | The resource ID of the deployed module | + +## Template references + +- [Automationaccounts/Modules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/modules) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/modules/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/carml/1.0.0/Microsoft.Automation/automationAccounts/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/readme.md new file mode 100644 index 000000000..8a35a9b67 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/readme.md @@ -0,0 +1,166 @@ +# Automation Accounts `[Microsoft.Automation/automationAccounts]` + +This module deploys an Azure Automation Account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Automation/automationAccounts` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/jobSchedules` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/modules` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/runbooks` | 2019-06-01 | +| `Microsoft.Automation/automationAccounts/schedules` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/softwareUpdateConfigurations` | 2019-06-01 | +| `Microsoft.Automation/automationAccounts/variables` | 2020-01-13-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | 2020-03-01-preview | +| `Microsoft.OperationsManagement/solutions` | 2015-11-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. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `gallerySolutions` | array | `[]` | | Optional. List of gallerySolutions to be created in the linked log analytics workspace | +| `jobSchedules` | _[jobSchedules](jobSchedules/readme.md)_ array | `[]` | | Optional. List of jobSchedules to be created in the automation account. | +| `linkedWorkspaceId` | string | | | Optional. ID of the log analytics workspace to be linked to the deployed automation account. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[JobLogs, JobStreams, DscNodeStatus]` | `[JobLogs, JobStreams, DscNodeStatus]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `modules` | _[modules](modules/readme.md)_ array | `[]` | | Optional. List of modules to be created in the automation account. | +| `name` | string | | | Required. Name of the Automation Account. | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `runbooks` | _[runbooks](runbooks/readme.md)_ array | `[]` | | Optional. List of runbooks to be created in the automation account. | +| `schedules` | _[schedules](schedules/readme.md)_ array | `[]` | | Optional. List of schedules to be created in the automation account. | +| `skuName` | string | `Basic` | `[Free, Basic]` | Optional. SKU name of the account. | +| `softwareUpdateConfigurations` | _[softwareUpdateConfigurations](softwareUpdateConfigurations/readme.md)_ array | `[]` | | Optional. List of softwareUpdateConfigurations to be created in the automation account | +| `systemAssignedIdentity` | bool | `False` | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the Automation Account resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `variables` | _[variables](variables/readme.md)_ array | `[]` | | Optional. List of variables to be created in the automation account. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed automation account | +| `resourceGroupName` | string | The resource group of the deployed automation account | +| `resourceId` | string | The resource ID of the deployed automation account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Automationaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts) +- [Automationaccounts/Jobschedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/jobSchedules) +- [Automationaccounts/Modules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/modules) +- [Automationaccounts/Runbooks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/runbooks) +- [Automationaccounts/Schedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/schedules) +- [Automationaccounts/Softwareupdateconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/softwareUpdateConfigurations) +- [Automationaccounts/Variables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/variables) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Solutions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) +- [Workspaces/Linkedservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-03-01-preview/workspaces/linkedServices) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/deploy.bicep new file mode 100644 index 000000000..48be20cae --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/deploy.bicep @@ -0,0 +1,90 @@ +@description('Required. Name of the Automation Account runbook.') +param name string + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@allowed([ + 'Graph' + 'GraphPowerShell' + 'GraphPowerShellWorkflow' + 'PowerShell' + 'PowerShellWorkflow' +]) +@description('Required. The type of the runbook.') +param runbookType string + +@description('Optional. The description of the runbook.') +param runbookDescription string = '' + +@description('Optional. The uri of the runbook content.') +param uri string = '' + +@description('Optional. The version of the runbook content.') +param version string = '' + +@description('Optional. ID of the runbook storage account.') +param scriptStorageAccountId string = '' + +@description('Optional. Time used as a basis for e.g. the schedule start date.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Automation Account resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = if (!empty(scriptStorageAccountId)) { + name: last(split(scriptStorageAccountId, '/')) + scope: resourceGroup(split(scriptStorageAccountId, '/')[2], split(scriptStorageAccountId, '/')[4]) +} + +var publishContentLink = empty(uri) ? null : { + uri: !empty(uri) ? (empty(scriptStorageAccountId) ? uri : '${uri}${storageAccount.listAccountSas('2021-04-01', accountSasProperties).accountSasToken}') : null + version: !empty(version) ? version : null +} + +resource runbook 'Microsoft.Automation/automationAccounts/runbooks@2019-06-01' = { + name: name + parent: automationAccount + location: location + tags: tags + properties: { + runbookType: runbookType + description: runbookDescription + publishContentLink: !empty(uri) ? publishContentLink : null + } +} + +@description('The name of the deployed runbook') +output name string = runbook.name + +@description('The resource ID of the deployed runbook') +output resourceId string = runbook.id + +@description('The resource group of the deployed runbook') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/readme.md new file mode 100644 index 000000000..ef083883f --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/readme.md @@ -0,0 +1,55 @@ +# Automation Account Runbooks `[Microsoft.Automation/automationAccounts/runbooks]` + +This module deploys an Azure Automation Account Runbook. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/runbooks` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | | Required. Name of the parent Automation Account. | +| `baseTime` | string | `[utcNow('u')]` | | Optional. Time used as a basis for e.g. the schedule start date. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | | | Required. Name of the Automation Account runbook. | +| `runbookDescription` | string | | | Optional. The description of the runbook. | +| `runbookType` | string | | `[Graph, GraphPowerShell, GraphPowerShellWorkflow, PowerShell, PowerShellWorkflow]` | Required. The type of the runbook. | +| `sasTokenValidityLength` | string | `PT8H` | | Optional. SAS token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `scriptStorageAccountId` | string | | | Optional. ID of the runbook storage account. | +| `tags` | object | `{object}` | | Optional. Tags of the Automation Account resource. | +| `uri` | string | | | Optional. The uri of the runbook content. | +| `version` | string | | | Optional. The version of the runbook content. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed runbook | +| `resourceGroupName` | string | The resource group of the deployed runbook | +| `resourceId` | string | The resource ID of the deployed runbook | + +## Template references + +- [Automationaccounts/Runbooks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/runbooks) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/runbooks/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/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/deploy.bicep new file mode 100644 index 000000000..ded932f9b --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/deploy.bicep @@ -0,0 +1,77 @@ +@description('Required. Name of the Automation Account schedule.') +param name string + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@description('Optional. The properties of the create Advanced Schedule.') +@metadata({ + monthDays: 'Days of the month that the job should execute on. Must be between 1 and 31.' + monthlyOccurrences: 'Occurrences of days within a month.' + weekDays: 'Days of the week that the job should execute on.' +}) +param advancedSchedule object = {} + +@description('Optional. The description of the schedule.') +param scheduleDescription string = '' + +@description('Optional. The end time of the schedule.') +param expiryTime string = '' + +@allowed([ + 'Day' + 'Hour' + 'Minute' + 'Month' + 'OneTime' + 'Week' +]) +@description('Optional. The frequency of the schedule.') +param frequency string = 'OneTime' + +@description('Optional. Anything') +param interval int = 0 + +@description('Optional. The start time of the schedule.') +param startTime string = '' + +@description('Optional. The time zone of the schedule.') +param timeZone string = '' + +@description('Optional. Time used as a basis for e.g. the schedule start date.') +param baseTime string = utcNow('u') + +@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 automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource schedule 'Microsoft.Automation/automationAccounts/schedules@2020-01-13-preview' = { + name: name + parent: automationAccount + properties: { + advancedSchedule: !empty(advancedSchedule) ? advancedSchedule : null + description: !empty(scheduleDescription) ? scheduleDescription : null + expiryTime: !empty(expiryTime) ? expiryTime : null + frequency: !empty(frequency) ? frequency : 'OneTime' + interval: (interval != 0) ? interval : null + startTime: !empty(startTime) ? startTime : dateTimeAdd(baseTime, 'PT10M') + timeZone: !empty(timeZone) ? timeZone : null + } +} + +@description('The name of the deployed schedule') +output name string = schedule.name + +@description('The resource ID of the deployed schedule') +output resourceId string = schedule.id + +@description('The resource group of the deployed schedule') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/readme.md new file mode 100644 index 000000000..623e5c3f8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/readme.md @@ -0,0 +1,37 @@ +# Automation Account Schedules `[Microsoft.Automation/automationAccounts/schedules]` + +This module deploys an Azure Automation Account Schedule. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/schedules` | 2020-01-13-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `advancedSchedule` | object | `{object}` | | Optional. The properties of the create Advanced Schedule. | +| `automationAccountName` | string | | | Required. Name of the parent Automation Account. | +| `baseTime` | string | `[utcNow('u')]` | | Optional. Time used as a basis for e.g. the schedule start date. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `expiryTime` | string | | | Optional. The end time of the schedule. | +| `frequency` | string | `OneTime` | `[Day, Hour, Minute, Month, OneTime, Week]` | Optional. The frequency of the schedule. | +| `interval` | int | | | Optional. Anything | +| `name` | string | | | Required. Name of the Automation Account schedule. | +| `scheduleDescription` | string | | | Optional. The description of the schedule. | +| `startTime` | string | | | Optional. The start time of the schedule. | +| `timeZone` | string | | | Optional. The time zone of the schedule. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed schedule | +| `resourceGroupName` | string | The resource group of the deployed schedule | +| `resourceId` | string | The resource ID of the deployed schedule | + +## Template references + +- [Automationaccounts/Schedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/schedules) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/schedules/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/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/deploy.bicep new file mode 100644 index 000000000..447aac7b6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/deploy.bicep @@ -0,0 +1,266 @@ +@description('Required. The name of the Deployment schedule.') +param name string + +@description('Required. Name of the parent Automation Account') +param automationAccountName string + +@description('Required. The operating system to be configured by the deployment schedule.') +@allowed([ + 'Windows' + 'Linux' +]) +param operatingSystem string + +@description('Required. Reboot setting for the deployment schedule.') +@allowed([ + 'IfRequired' + 'Never' + 'RebootOnly' + 'Always' +]) +param rebootSetting string + +@description('Required. The frequency of the deployment schedule. When using \'Hour\', \'Day\', \'Week\' or \'Month\', an interval needs to be provided.') +@allowed([ + 'OneTime' + 'Hour' + 'Day' + 'Week' + 'Month' +]) +param frequency string + +@description('Optional. Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601') +param maintenanceWindow string = 'PT2H' + +@description('Optional. Update classification included in the deployment schedule.') +@allowed([ + 'Critical' + 'Security' + 'UpdateRollup' + 'FeaturePack' + 'ServicePack' + 'Definition' + 'Tools' + 'Updates' + 'Other' +]) +param updateClassifications array = [ + 'Critical' + 'Security' +] + +@description('Optional. KB numbers or Linux packages excluded in the deployment schedule.') +param excludeUpdates array = [] + +@description('Optional. KB numbers or Linux packages included in the deployment schedule.') +param includeUpdates array = [] + +@description('Optional. Specify the resources to scope the deployment schedule to.') +param scopeByResources array = [ + subscription().id +] + +@description('Optional. Specify tags to which to scope the deployment schedule to.') +param scopeByTags object = {} + +@description('Optional. Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B).') +@allowed([ + 'All' + 'Any' +]) +param scopeByTagsOperation string = 'All' + +@description('Optional. Specify locations to which to scope the deployment schedule to.') +param scopeByLocations array = [] + +@description('Optional. Parameters provided to the task running before the deployment schedule.') +param preTaskParameters object = {} + +@description('Optional. The source of the task running before the deployment schedule.') +param preTaskSource string = '' + +@description('Optional. Parameters provided to the task running after the deployment schedule.') +param postTaskParameters object = {} + +@description('Optional. The source of the task running after the deployment schedule.') +param postTaskSource string = '' + +@description('Optional. The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc.') +@maxValue(100) +param interval int = 1 + +@description('Optional. Enables the deployment schedule.') +param isEnabled bool = true + +@description('Optional. Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID.') +param timeZone string = 'UTC' + +@description('Optional. Array of functions from a Log Analytics workspace, used to scope the deployment schedule.') +param nonAzureQueries array = [] + +@description('Optional. List of azure resource IDs for azure virtual machines in scope for the deployment schedule.') +param azureVirtualMachines array = [] + +@description('Optional. List of names of non-azure machines in scope for the deployment schedule.') +param nonAzureComputerNames array = [] + +@description('Optional. Required when used with frequency \'Week\'. Specified the day of the week to run the deployment schedule.') +@allowed([ + 'Monday' + 'Tuesday' + 'Wednesday' + 'Thursday' + 'Friday' + 'Saturday' + 'Sunday' +]) +param weekDays array = [] + +@description('Optional. Can be used with frequency \'Month\'. Provides the specific days of the month to run the deployment schedule.') +@allowed([ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 +]) +param monthDays array = [] + +@description('Optional. Can be used with frequency \'Month\'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule.') +param monthlyOccurrences array = [] + +@description('Optional. The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00.') +param startTime string = '' + +@description('Optional. The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00') +param expiryTime string = '' + +@description('Optional. The expiry time\'s offset in minutes.') +param expiryTimeOffsetMinutes int = 0 + +@description('Optional. The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00') +param nextRun string = '' + +@description('Optional. The next run\'s offset in minutes.') +param nextRunOffsetMinutes int = 0 + +@description('Optional. The schedules description.') +param scheduleDescription string = '' + +@description('Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule.') +param baseTime string = utcNow('u') + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var updateClassifications_var = '${replace(replace(replace(replace(string(updateClassifications), ',', ', '), '[', ''), ']', ''), '"', '')}' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource softwareUpdateConfiguration 'Microsoft.Automation/automationAccounts/softwareUpdateConfigurations@2019-06-01' = { + name: name + parent: automationAccount + properties: { + updateConfiguration: { + operatingSystem: operatingSystem + duration: maintenanceWindow + linux: ((operatingSystem == 'Linux') ? { + excludedPackageNameMasks: excludeUpdates + includedPackageNameMasks: includeUpdates + includedPackageClassifications: updateClassifications_var + rebootSetting: rebootSetting + } : null) + windows: ((operatingSystem == 'Windows') ? { + excludedKbNumbers: excludeUpdates + includedKbNumbers: includeUpdates + includedUpdateClassifications: updateClassifications_var + rebootSetting: rebootSetting + } : null) + targets: { + azureQueries: [ + { + scope: scopeByResources + tagSettings: { + tags: scopeByTags + filterOperator: scopeByTagsOperation + } + locations: scopeByLocations + } + ] + nonAzureQueries: nonAzureQueries + } + azureVirtualMachines: azureVirtualMachines + nonAzureComputerNames: nonAzureComputerNames + } + tasks: { + preTask: { + parameters: (empty(preTaskParameters) ? null : preTaskParameters) + source: (empty(preTaskSource) ? null : preTaskSource) + } + postTask: { + parameters: (empty(postTaskParameters) ? null : postTaskParameters) + source: (empty(postTaskSource) ? null : postTaskSource) + } + } + scheduleInfo: { + interval: interval + frequency: frequency + isEnabled: isEnabled + timeZone: timeZone + advancedSchedule: { + weekDays: (empty(weekDays) ? null : weekDays) + monthDays: (empty(monthDays) ? null : monthDays) + monthlyOccurrences: (empty(monthlyOccurrences) ? null : monthlyOccurrences) + } + startTime: (empty(startTime) ? dateTimeAdd(baseTime, 'PT10M') : startTime) + expiryTime: expiryTime + expiryTimeOffsetMinutes: expiryTimeOffsetMinutes + nextRun: nextRun + nextRunOffsetMinutes: nextRunOffsetMinutes + description: scheduleDescription + } + } +} + +@description('The name of the deployed softwareUpdateConfiguration') +output name string = softwareUpdateConfiguration.name + +@description('The resource ID of the deployed softwareUpdateConfiguration') +output resourceId string = softwareUpdateConfiguration.id + +@description('The resource group of the deployed softwareUpdateConfiguration') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/readme.md new file mode 100644 index 000000000..7476b7a8a --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/readme.md @@ -0,0 +1,105 @@ +# Automation Account Software Update Configurations `[Microsoft.Automation/automationAccounts/softwareUpdateConfigurations]` + +This module deploys an Azure Automation Account Software update Configuration. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/softwareUpdateConfigurations` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | | Required. Name of the parent Automation Account | +| `azureVirtualMachines` | array | `[]` | | Optional. List of azure resource IDs for azure virtual machines in scope for the deployment schedule. | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `excludeUpdates` | array | `[]` | | Optional. KB numbers or Linux packages excluded in the deployment schedule. | +| `expiryTime` | string | | | Optional. The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00 | +| `expiryTimeOffsetMinutes` | int | | | Optional. The expiry time's offset in minutes. | +| `frequency` | string | | `[OneTime, Hour, Day, Week, Month]` | Required. The frequency of the deployment schedule. When using 'Hour', 'Day', 'Week' or 'Month', an interval needs to be provided. | +| `includeUpdates` | array | `[]` | | Optional. KB numbers or Linux packages included in the deployment schedule. | +| `interval` | int | `1` | | Optional. The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc. | +| `isEnabled` | bool | `True` | | Optional. Enables the deployment schedule. | +| `maintenanceWindow` | string | `PT2H` | | Optional. Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601 | +| `monthDays` | array | `[]` | `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]` | Optional. Can be used with frequency 'Month'. Provides the specific days of the month to run the deployment schedule. | +| `monthlyOccurrences` | array | `[]` | | Optional. Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule. | +| `name` | string | | | Required. The name of the Deployment schedule. | +| `nextRun` | string | | | Optional. The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00 | +| `nextRunOffsetMinutes` | int | | | Optional. The next run's offset in minutes. | +| `nonAzureComputerNames` | array | `[]` | | Optional. List of names of non-azure machines in scope for the deployment schedule. | +| `nonAzureQueries` | array | `[]` | | Optional. Array of functions from a Log Analytics workspace, used to scope the deployment schedule. | +| `operatingSystem` | string | | `[Windows, Linux]` | Required. The operating system to be configured by the deployment schedule. | +| `postTaskParameters` | object | `{object}` | | Optional. Parameters provided to the task running after the deployment schedule. | +| `postTaskSource` | string | | | Optional. The source of the task running after the deployment schedule. | +| `preTaskParameters` | object | `{object}` | | Optional. Parameters provided to the task running before the deployment schedule. | +| `preTaskSource` | string | | | Optional. The source of the task running before the deployment schedule. | +| `rebootSetting` | string | | `[IfRequired, Never, RebootOnly, Always]` | Required. Reboot setting for the deployment schedule. | +| `scheduleDescription` | string | | | Optional. The schedules description. | +| `scopeByLocations` | array | `[]` | | Optional. Specify locations to which to scope the deployment schedule to. | +| `scopeByResources` | array | `[[subscription().id]]` | | Optional. Specify the resources to scope the deployment schedule to. | +| `scopeByTags` | object | `{object}` | | Optional. Specify tags to which to scope the deployment schedule to. | +| `scopeByTagsOperation` | string | `All` | `[All, Any]` | Optional. Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B). | +| `startTime` | string | | | Optional. The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00. | +| `timeZone` | string | `UTC` | | Optional. Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID. | +| `updateClassifications` | array | `[Critical, Security]` | `[Critical, Security, UpdateRollup, FeaturePack, ServicePack, Definition, Tools, Updates, Other]` | Optional. Update classification included in the deployment schedule. | +| `weekDays` | array | `[]` | `[Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]` | Optional. Required when used with frequency 'Week'. Specified the day of the week to run the deployment schedule. | + +### Parameter Usage: `scopeByTags` + +Provide tag keys, with an array of values, filtering in machines that should be included in the deployment schedule. + +| Property name | Type | Possible values | Description | +| :------------ | :---- | :-------------- | :---------- | +| \ | array | string | tag values | + +```json +"scopeByTags": { + "value": { + "Update": [ + "Automatic" + ], + "MaintenanceWindow": [ + "1-Sat-22" + ] + } +} +``` + +### Parameter Usage: `monthlyOccurrences` + +Occurrences of days within a month. + +| Property name | Type | Possible values | Description | +| :------------ | :----- | :------------------------------------------------------------- | :----------------------------------------------------------------------------------- | +| `occurance` | int | 1-5 | Occurrence of the week within the month. Must be between 1 and 5, where 5 is "last". | +| `day` | string | Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday | Day of the occurrence. | + +```json +"monthlyOccurrences": { + "value": [ + { + "occurrence": 1, + "day": "Monday" + }, + { + "occurrence": 2, + "day": "Friday" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed softwareUpdateConfiguration | +| `resourceGroupName` | string | The resource group of the deployed softwareUpdateConfiguration | +| `resourceId` | string | The resource ID of the deployed softwareUpdateConfiguration | + +## Template references + +- [Automationaccounts/Softwareupdateconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/softwareUpdateConfigurations) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/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/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/deploy.bicep b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/deploy.bicep new file mode 100644 index 000000000..6473a994f --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/deploy.bicep @@ -0,0 +1,45 @@ +@sys.description('Required. Name of the parent Automation Account') +param automationAccountName string + +@sys.description('Required. The name of the variable.') +param name string + +@sys.description('Required. The value of the variable.') +param value string + +@sys.description('Optional. The description of the variable.') +param description string = '' + +@sys.description('Optional. If the variable should be encrypted.') +param isEncrypted bool = false + +@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 automationAccount 'Microsoft.Automation/automationAccounts@2021-06-22' existing = { + name: automationAccountName +} + +resource variable 'Microsoft.Automation/automationAccounts/variables@2020-01-13-preview' = { + name: name + parent: automationAccount + properties: { + description: description + isEncrypted: isEncrypted + value: value + } +} + +@sys.description('The name of the deployed variable') +output name string = variable.name + +@sys.description('The resource ID of the deployed variable') +output resourceId string = variable.id + +@sys.description('The resource group of the deployed variable') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/readme.md b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/readme.md new file mode 100644 index 000000000..3ebee7601 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/readme.md @@ -0,0 +1,56 @@ +# Automation Account Variables `[Microsoft.Automation/automationAccounts/variables]` + +This module deploys a variable to an Azure Automation Account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/variables` | 2020-01-13-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | | Required. Name of the parent Automation Account | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `description` | string | | | Optional. The description of the variable. | +| `isEncrypted` | bool | | | Optional. If the variable should be encrypted. | +| `name` | string | | | Required. The name of the variable. | +| `value` | string | | | Required. The value of the variable. | + +### Parameter Usage: `value` + +```json + //Boolean format + "value": { + "value": "false" + } + + //DateTime format + "value": { + "value": "\"\\/Date(1637934042656)\\/\"" + } + + //Integer format + "value": { + "value": "500" + } + + //String format + "value": { + "value": "\"TestString\"" + } +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed variable | +| `resourceGroupName` | string | The resource group of the deployed variable | +| `resourceId` | string | The resource ID of the deployed variable | + +## Template references + +- [Automationaccounts/Variables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/variables) diff --git a/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/variables/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/carml/1.0.0/Microsoft.Automation/automationAccounts/version.json b/carml/1.0.0/Microsoft.Automation/automationAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Automation/automationAccounts/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/carml/1.0.0/Microsoft.Batch/batchAccounts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Batch/batchAccounts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Batch/batchAccounts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Batch/batchAccounts/.parameters/parameters.json b/carml/1.0.0/Microsoft.Batch/batchAccounts/.parameters/parameters.json new file mode 100644 index 000000000..340396fc9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Batch/batchAccounts/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azbaweux001" + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Batch/batchAccounts/deploy.bicep b/carml/1.0.0/Microsoft.Batch/batchAccounts/deploy.bicep new file mode 100644 index 000000000..56f965ed4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Batch/batchAccounts/deploy.bicep @@ -0,0 +1,114 @@ +@description('Required. Name of the Azure Batch') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ServiceLog' +]) +param logsToEnable array = [ + 'ServiceLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource batchAccount 'Microsoft.Batch/batchAccounts@2020-09-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource batchAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${batchAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: batchAccount +} + +resource batchAccount_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${batchAccount.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: batchAccount +} + +@description('The name of the batch account') +output name string = batchAccount.name + +@description('The resource ID of the batch account') +output resourceId string = batchAccount.id + +@description('The resource group the batch account was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Batch/batchAccounts/readme.md b/carml/1.0.0/Microsoft.Batch/batchAccounts/readme.md new file mode 100644 index 000000000..ae2cce7e1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Batch/batchAccounts/readme.md @@ -0,0 +1,57 @@ +# Batch Accounts `[Microsoft.Batch/batchAccounts]` + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Batch/batchAccounts` | 2020-09-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-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 | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ServiceLog]` | `[ServiceLog]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the Azure Batch | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the batch account | +| `resourceGroupName` | string | The resource group the batch account was deployed into | +| `resourceId` | string | The resource ID of the batch account | + +## Template references + +- [Batchaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Batch/2020-09-01/batchAccounts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.0/Microsoft.Batch/batchAccounts/version.json b/carml/1.0.0/Microsoft.Batch/batchAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Batch/batchAccounts/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/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_privateEndpoints.bicep b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_privateEndpoints.bicep new file mode 100644 index 000000000..4e7cd75dc --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_privateEndpoints.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpoint object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpoint, 'name') ? (empty(privateEndpoint.name) ? '${privateEndpointResourceName}-${privateEndpoint.service}' : privateEndpoint.name) : '${privateEndpointResourceName}-${privateEndpoint.service}') + subnetResourceId: privateEndpoint.subnetResourceId + service: [ + privateEndpoint.service + ] + privateDnsZoneResourceIds: (contains(privateEndpoint, 'privateDnsZoneResourceIds') ? privateEndpoint.privateDnsZoneResourceIds : []) + customDnsConfigs: (contains(privateEndpoint, 'customDnsConfigs') ? (empty(privateEndpoint.customDnsConfigs) ? null : privateEndpoint.customDnsConfigs) : null) +} + +resource privateEndpoint_resource 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_resource.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..fa64b26cb --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.bicep/nested_rbac.bicep @@ -0,0 +1,49 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Cognitive Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68') + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3') + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f') + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c') + 'Cognitive Services Custom Vision Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73') + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b') + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c') + 'Cognitive Services Face Recognizer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9894cab4-e18a-44aa-828b-cb588cd6f2d7') + 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cb43c632-a144-4ec5-977c-e80c4affc34a') + 'Cognitive Services Metrics Advisor User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3b20f47b-3825-43cb-8114-4bd2201156a8') + 'Cognitive Services QnA Maker Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025') + 'Cognitive Services QnA Maker Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126') + 'Cognitive Services Speech Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0e75ca1e-0464-4b4d-8b93-68208a576181') + 'Cognitive Services Speech User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f2dc8367-1007-4938-bd23-fe263f013447') + 'Cognitive Services User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource account 'Microsoft.CognitiveServices/accounts@2017-04-18' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(account.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: account +}] diff --git a/carml/1.0.0/Microsoft.CognitiveServices/accounts/.parameters/parameters.json b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.parameters/parameters.json new file mode 100644 index 000000000..bc8e4e4d6 --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/.parameters/parameters.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cgs-x-001" + }, + "kind": { + "value": "Face" + }, + "sku": { + "value": "F0" + }, + "cuaId": { + "value": "00000000-0000-0000-0000-000000000000" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.CognitiveServices/accounts/deploy.bicep b/carml/1.0.0/Microsoft.CognitiveServices/accounts/deploy.bicep new file mode 100644 index 000000000..41343fb13 --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/deploy.bicep @@ -0,0 +1,237 @@ +@description('Required. The name of Cognitive Services account') +param name string + +@description('Required. Kind of the Cognitive Services. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'sku\' for your Azure region.') +@allowed([ + 'AnomalyDetector' + 'Bing.Autosuggest.v7' + 'Bing.CustomSearch' + 'Bing.EntitySearch' + 'Bing.Search.v7' + 'Bing.SpellCheck.v7' + 'CognitiveServices' + 'ComputerVision' + 'ContentModerator' + 'CustomVision.Prediction' + 'CustomVision.Training' + 'Face' + 'FormRecognizer' + 'ImmersiveReader' + 'Internal.AllInOne' + 'LUIS' + 'LUIS.Authoring' + 'Personalizer' + 'QnAMaker' + 'SpeechServices' + 'TextAnalytics' + 'TextTranslation' +]) +param kind string + +@description('Optional. SKU of the Cognitive Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'sku\' for your Azure region.') +@allowed([ + 'C2' + 'C3' + 'C4' + 'F0' + 'F1' + 'S' + 'S0' + 'S1' + 'S10' + 'S2' + 'S3' + 'S4' + 'S5' + 'S6' + 'S7' + 'S8' + 'S9' +]) +param sku string = 'S0' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Subdomain name used for token-based authentication. Required if \'networkAcls\' are set.') +param customSubDomainName string = '' + +@description('Optional. Subdomain name used for token-based authentication. Must be set if \'networkAcls\' are set.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Service endpoint object information') +param networkAcls object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Audit' + 'RequestResponse' +]) +param logsToEnable array = [ + 'Audit' + 'RequestResponse' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var networkAcls_var = { + defaultAction: ((empty(networkAcls)) ? null : networkAcls.defaultAction) + virtualNetworkRules: ((empty(networkAcls)) ? null : ((length(networkAcls.virtualNetworkRules) == 0) ? [] : networkAcls.virtualNetworkRules)) + ipRules: ((empty(networkAcls)) ? null : ((length(networkAcls.ipRules) == 0) ? [] : networkAcls.ipRules)) +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource cognitiveServices 'Microsoft.CognitiveServices/accounts@2017-04-18' = { + name: name + kind: kind + identity: identity + location: location + tags: tags + sku: { + name: sku + } + properties: { + customSubDomainName: (empty(customSubDomainName) ? null : customSubDomainName) + networkAcls: ((empty(networkAcls)) ? null : networkAcls_var) + publicNetworkAccess: publicNetworkAccess + } +} + +resource cognitiveServices_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${cognitiveServices.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: cognitiveServices +} + +resource cognitiveServices_diagnosticSettingName 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${cognitiveServices.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: cognitiveServices +} + +module cognitiveServices_privateEndpoints '.bicep/nested_privateEndpoints.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-CognitiveServices-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: cognitiveServices.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpoint: privateEndpoint + tags: tags + } +}] + +module cognitiveServices_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-CognitiveServices-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: cognitiveServices.id + } +}] + +@description('The name of the cognitive services account') +output name string = cognitiveServices.name + +@description('The resource ID of the cognitive services account') +output resourceId string = cognitiveServices.id + +@description('The resource group the cognitive services account was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The service endpoint of the cognitive services account') +output endpoint string = cognitiveServices.properties.endpoint + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(cognitiveServices.identity, 'principalId') ? cognitiveServices.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.CognitiveServices/accounts/readme.md b/carml/1.0.0/Microsoft.CognitiveServices/accounts/readme.md new file mode 100644 index 000000000..0868c9369 --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/readme.md @@ -0,0 +1,208 @@ +# Cognitive Services `[Microsoft.CognitiveServices/accounts]` + +This module deploys different kinds of cognitive services resources + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.CognitiveServices/accounts` | 2017-04-18 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customSubDomainName` | string | | | Optional. Subdomain name used for token-based authentication. Required if 'networkAcls' are set. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `kind` | string | | `[AnomalyDetector, Bing.Autosuggest.v7, Bing.CustomSearch, Bing.EntitySearch, Bing.Search.v7, Bing.SpellCheck.v7, CognitiveServices, ComputerVision, ContentModerator, CustomVision.Prediction, CustomVision.Training, Face, FormRecognizer, ImmersiveReader, Internal.AllInOne, LUIS, LUIS.Authoring, Personalizer, QnAMaker, SpeechServices, TextAnalytics, TextTranslation]` | Required. Kind of the Cognitive Services. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'sku' for your Azure region. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[Audit, RequestResponse]` | `[Audit, RequestResponse]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of Cognitive Services account | +| `networkAcls` | object | `{object}` | | Optional. Service endpoint object information | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `publicNetworkAccess` | string | `Enabled` | `[Enabled, Disabled]` | Optional. Subdomain name used for token-based authentication. Must be set if 'networkAcls' are set. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `S0` | `[C2, C3, C4, F0, F1, S, S0, S1, S10, S2, S3, S4, S5, S6, S7, S8, S9]` | Optional. SKU of the Cognitive Services resource. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'sku' for your Azure region. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. + +- Although not strictly required, it is highly recommened to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "vault", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "id": "/subscriptions//resourceGroups/resourceGroup/providers/Microsoft.Network/virtualNetworks//subnets/", + "ignoreMissingVnetServiceEndpoint": false + } + ], + "ipRules": [ + { + "value": "1.1.1.1" + }, + { + "value": "" + } + ] + } +}, +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `endpoint` | string | The service endpoint of the cognitive services account | +| `name` | string | The name of the cognitive services account | +| `resourceGroupName` | string | The resource group the cognitive services account was deployed into | +| `resourceId` | string | The resource ID of the cognitive services account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +- Not all combinations of parameters `kind` and `sku` are valid and they may vary in different Azure Regions. Please use PowerShell CmdLet `Get-AzCognitiveServicesAccountSku` or another methods to determine valid values in your region. +- Not all kinds of Cognitive Services support virtual networks. Please visit the link below to determine supported services. + +## Template references + +- [Accounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.CognitiveServices/2017-04-18/accounts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.CognitiveServices/accounts/version.json b/carml/1.0.0/Microsoft.CognitiveServices/accounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.CognitiveServices/accounts/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/carml/1.0.0/Microsoft.Compute/availabilitySets/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/availabilitySets/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..028ee46c6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource availabilitySet 'Microsoft.Compute/availabilitySets@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(availabilitySet.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: availabilitySet +}] diff --git a/carml/1.0.0/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json new file mode 100644 index 000000000..99d2414f7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avs-min-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/availabilitySets/.parameters/parameters.json b/carml/1.0.0/Microsoft.Compute/availabilitySets/.parameters/parameters.json new file mode 100644 index 000000000..cfa2eab50 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avs-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "proximityPlacementGroupId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/proximityPlacementGroups/adp-<>-az-ppg-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/availabilitySets/deploy.bicep b/carml/1.0.0/Microsoft.Compute/availabilitySets/deploy.bicep new file mode 100644 index 000000000..008953afd --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/deploy.bicep @@ -0,0 +1,82 @@ +@description('Required. The name of the availability set that is being created.') +param name string + +@description('Optional. The number of fault domains to use.') +param availabilitySetFaultDomain int = 2 + +@description('Optional. The number of update domains to use.') +param availabilitySetUpdateDomain int = 5 + +@description('Optional. Sku of the availability set. Use \'Aligned\' for virtual machines with managed disks and \'Classic\' for virtual machines with unmanaged disks.') +param availabilitySetSku string = 'Aligned' + +@description('Optional. Resource ID of a proximity placement group.') +param proximityPlacementGroupId string = '' + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@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 availabilitySet 'Microsoft.Compute/availabilitySets@2021-07-01' = { + name: name + location: location + tags: tags + properties: { + platformFaultDomainCount: availabilitySetFaultDomain + platformUpdateDomainCount: availabilitySetUpdateDomain + proximityPlacementGroup: !empty(proximityPlacementGroupId) ? { + id: proximityPlacementGroupId + } : null + } + sku: { + name: availabilitySetSku + } +} + +resource availabilitySet_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${availabilitySet.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: availabilitySet +} + +module availabilitySet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AvSet-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: availabilitySet.id + } +}] + +@description('The name of the availability set') +output name string = availabilitySet.name + +@description('The resource ID of the availability set') +output resourceId string = availabilitySet.id + +@description('The resource group the availability set was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Compute/availabilitySets/readme.md b/carml/1.0.0/Microsoft.Compute/availabilitySets/readme.md new file mode 100644 index 000000000..e21c36dac --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/readme.md @@ -0,0 +1,79 @@ +# Availability Sets `[Microsoft.Compute/availabilitySets]` + +This template deploys an availability set + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/availabilitySets` | 2021-07-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `availabilitySetFaultDomain` | int | `2` | | Optional. The number of fault domains to use. | +| `availabilitySetSku` | string | `Aligned` | | Optional. Sku of the availability set. Use 'Aligned' for virtual machines with managed disks and 'Classic' for virtual machines with unmanaged disks. | +| `availabilitySetUpdateDomain` | int | `5` | | Optional. The number of update domains to use. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Resource location. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the availability set that is being created. | +| `proximityPlacementGroupId` | string | | | Optional. Resource ID of a proximity placement group. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the availability set resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the availability set | +| `resourceGroupName` | string | The resource group the availability set was deployed into | +| `resourceId` | string | The resource ID of the availability set | + +## Template references + +- [Availabilitysets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/availabilitySets) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Compute/availabilitySets/version.json b/carml/1.0.0/Microsoft.Compute/availabilitySets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/availabilitySets/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/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep new file mode 100644 index 000000000..64765196a --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep @@ -0,0 +1,36 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. The access policy name') +param name string = 'add' + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the access policies assignment') +output name string = policies.name + +@description('The resource ID of the access policies assignment') +output resourceId string = policies.id diff --git a/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..8528dbdda --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep @@ -0,0 +1,38 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(diskEncryptionSet.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: diskEncryptionSet +}] diff --git a/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json new file mode 100644 index 000000000..9ad9ed7c5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-des-x-001" + }, + "keyVaultId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "keyUrl": { + "value": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5" // ID must be updated for new keys + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/deploy.bicep b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/deploy.bicep new file mode 100644 index 000000000..26cc93f6a --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. The name of the disk encryption set that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@description('Required. Resource ID of the KeyVault containing the key or secret.') +param keyVaultId string + +@description('Required. Key URL (with version) pointing to a key or secret in KeyVault.') +param keyUrl string + +@description('Optional. The type of key used to encrypt the data of the disk. For security reasons, it is recommended to set encryptionType to EncryptionAtRestWithPlatformAndCustomerKeys') +@allowed([ + 'EncryptionAtRestWithCustomerKey' + 'EncryptionAtRestWithPlatformAndCustomerKeys' +]) +param encryptionType string = 'EncryptionAtRestWithPlatformAndCustomerKeys' + +@description('Optional. Set this flag to true to enable auto-updating of this disk encryption set to the latest key version.') +param rotationToLatestKeyVersionEnabled bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the disk encryption resource.') +param tags object = {} + +@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 diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + activeKey: { + sourceVault: { + id: keyVaultId + } + keyUrl: keyUrl + } + encryptionType: encryptionType + rotationToLatestKeyVersionEnabled: rotationToLatestKeyVersionEnabled + } +} + +module keyVaultAccessPolicies '.bicep/nested_kvAccessPolicy.bicep' = { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-KVAccessPolicies' + params: { + keyVaultName: last(split(keyVaultId, '/')) + accessPolicies: [ + { + tenantId: subscription().tenantId + objectId: diskEncryptionSet.identity.principalId + permissions: { + keys: [ + 'get' + 'wrapKey' + 'unwrapKey' + ] + secrets: [] + certificates: [] + } + } + ] + } + // This is to support access policies to KV in different subscription and resource group than the disk encryption set. + scope: resourceGroup(split(keyVaultId, '/')[2], split(keyVaultId, '/')[4]) +} + +module diskEncryptionSet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: diskEncryptionSet.id + } +}] + +@description('The resource ID of the disk encryption set') +output resourceId string = diskEncryptionSet.id + +@description('The name of the disk encryption set') +output name string = diskEncryptionSet.name + +@description('The resource group the disk encryption set was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the disk encryption set') +output systemAssignedPrincipalId string = diskEncryptionSet.identity.principalId + +@description('The name of the key vault with the disk encryption key') +output keyVaultName string = last(split(keyVaultId, '/')) diff --git a/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/readme.md b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/readme.md new file mode 100644 index 000000000..c3c63428f --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/readme.md @@ -0,0 +1,80 @@ +# Disk Encryption Sets `[Microsoft.Compute/diskEncryptionSets]` + +This template deploys a disk encryption set. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/diskEncryptionSets` | 2021-04-01 | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-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 | +| `encryptionType` | string | `EncryptionAtRestWithPlatformAndCustomerKeys` | `[EncryptionAtRestWithCustomerKey, EncryptionAtRestWithPlatformAndCustomerKeys]` | Optional. The type of key used to encrypt the data of the disk. For security reasons, it is recommended to set 'encryptionType' to 'EncryptionAtRestWithPlatformAndCustomerKeys' | +| `keyUrl` | string | | | Required. Key URL (with version) pointing to a key or secret in KeyVault. | +| `keyVaultId` | string | | | Required. Resource ID of the KeyVault containing the key or secret. | +| `location` | string | `[resourceGroup().location]` | | Optional. Resource location. | +| `name` | string | | | Required. The name of the disk encryption set that is being created. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `rotationToLatestKeyVersionEnabled` | bool | | | Optional. Set this flag to true to enable auto-updating of this disk encryption set to the latest key version. | +| `tags` | object | `{object}` | | Optional. Tags of the disk encryption resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault with the disk encryption key | +| `name` | string | The name of the disk encryption set | +| `resourceGroupName` | string | The resource group the disk encryption set was deployed into | +| `resourceId` | string | The resource ID of the disk encryption set | +| `systemAssignedPrincipalId` | string | The principal ID of the disk encryption set | + +## Template references + +- [Diskencryptionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/diskEncryptionSets) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/version.json b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/diskEncryptionSets/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/carml/1.0.0/Microsoft.Compute/disks/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/disks/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/disks/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/disks/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..30579bd53 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource disk 'Microsoft.Compute/disks@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(disk.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: disk +}] diff --git a/carml/1.0.0/Microsoft.Compute/disks/.parameters/image.parameters.json b/carml/1.0.0/Microsoft.Compute/disks/.parameters/image.parameters.json new file mode 100644 index 000000000..d6934ac64 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/.parameters/image.parameters.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-image-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "createOption": { + "value": "FromImage" + }, + "imageReferenceId": { + "value": "/Subscriptions/<>/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2016-Datacenter/Versions/14393.4906.2112080838" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/disks/.parameters/import.parameters.json b/carml/1.0.0/Microsoft.Compute/disks/.parameters/import.parameters.json new file mode 100644 index 000000000..a09908e11 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/.parameters/import.parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-import-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "createOption": { + "value": "Import" + }, + "sourceUri": { + "value": "https://adp<>azsax001.blob.core.windows.net/vhds/adp-<>-az-imgt-x-001.vhd" + }, + "storageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/disks/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Compute/disks/.parameters/min.parameters.json new file mode 100644 index 000000000..d19f33a37 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/.parameters/min.parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-min-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "diskSizeGB": { + "value": 1 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/disks/.parameters/parameters.json b/carml/1.0.0/Microsoft.Compute/disks/.parameters/parameters.json new file mode 100644 index 000000000..3608893d9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-x-001" + }, + "sku": { + "value": "UltraSSD_LRS" + }, + "diskSizeGB": { + "value": 128 + }, + "logicalSectorSize": { + "value": 512 + }, + "diskIOPSReadWrite": { + "value": 500 + }, + "diskMBpsReadWrite": { + "value": 60 + }, + "osType": { + "value": "Windows" + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/disks/deploy.bicep b/carml/1.0.0/Microsoft.Compute/disks/deploy.bicep new file mode 100644 index 000000000..e66713dc5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/deploy.bicep @@ -0,0 +1,188 @@ +@description('Required. The name of the disk that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'Standard_LRS' + 'Premium_LRS' + 'StandardSSD_LRS' + 'UltraSSD_LRS' + 'Premium_ZRS' + 'Premium_ZRS' +]) +@description('Required. The disks sku name. Can be .') +param sku string + +@description('Optional. Set to true to enable bursting beyond the provisioned performance target of the disk.') +param burstingEnabled bool = false + +@description('Optional. Percentage complete for the background copy when a resource is created via the CopyStart operation.') +param completionPercent int = 100 + +@allowed([ + 'Attach' + 'Copy' + 'CopyStart' + 'Empty' + 'FromImage' + 'Import' + 'ImportSecure' + 'Restore' + 'Upload' + 'UploadPreparedSecure' +]) +@description('Optional. Sources of a disk creation.') +param createOption string = 'Empty' + +@description('Optional. A relative uri containing either a Platform Image Repository or user image reference.') +param imageReferenceId string = '' + +@description('Optional. Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096.') +param logicalSectorSize int = 4096 + +@description('Optional. If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state.') +param securityDataUri string = '' + +@description('Optional. If create option is Copy, this is the ARM id of the source snapshot or disk.') +param sourceResourceId string = '' + +@description('Optional. If create option is Import, this is the URI of a blob to be imported into a managed disk.') +param sourceUri string = '' + +@description('Optional. Required if create option is Import. The Azure Resource Manager identifier of the storage account containing the blob to import as a disk') +param storageAccountId string = '' + +@description('Optional. If create option is Upload, this is the size of the contents of the upload including the VHD footer.') +param uploadSizeBytes int = 20972032 + +@description('Optional. If create option is empty, this field is mandatory and it indicates the size of the disk to create.') +param diskSizeGB int = 0 + +@description('Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks.') +param diskIOPSReadWrite int = 0 + +@description('Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks.') +param diskMBpsReadWrite int = 0 + +@allowed([ + 'V1' + 'V2' +]) +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only.') +param hyperVGeneration string = 'V2' + +@description('Optional. The maximum number of VMs that can attach to the disk at the same time. Default value is 0.') +param maxShares int = 1 + +@allowed([ + 'AllowAll' + 'AllowPrivate' + 'DenyAll' +]) +@description('Optional. Policy for accessing the disk via network.') +param networkAccessPolicy string = 'DenyAll' + +@allowed([ + 'Windows' + 'Linux' + '' +]) +@description('Optional. Sources of a disk creation.') +param osType string = '' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Policy for controlling export on the disk.') +param publicNetworkAccess string = 'Disabled' + +@description('Optional. True if the image from which the OS disk is created supports accelerated networking.') +param acceleratedNetwork bool = false + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@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 disk 'Microsoft.Compute/disks@2021-08-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + } + properties: { + burstingEnabled: burstingEnabled + completionPercent: completionPercent + creationData: { + createOption: createOption + imageReference: createOption != 'FromImage' ? null : { + id: imageReferenceId + } + logicalSectorSize: contains(sku, 'Ultra') ? logicalSectorSize : null + securityDataUri: createOption == 'ImportSecure' ? securityDataUri : null + sourceResourceId: createOption == 'Copy' ? sourceResourceId : null + sourceUri: createOption == 'Import' ? sourceUri : null + storageAccountId: createOption == 'Import' ? storageAccountId : null + uploadSizeBytes: createOption == 'Upload' ? uploadSizeBytes : null + } + diskIOPSReadWrite: contains(sku, 'Ultra') ? diskIOPSReadWrite : null + diskMBpsReadWrite: contains(sku, 'Ultra') ? diskMBpsReadWrite : null + diskSizeGB: createOption == 'Empty' ? diskSizeGB : null + hyperVGeneration: empty(osType) ? null : hyperVGeneration + maxShares: maxShares + networkAccessPolicy: networkAccessPolicy + osType: empty(osType) ? null : osType + publicNetworkAccess: publicNetworkAccess + supportedCapabilities: empty(osType) ? {} : { + acceleratedNetwork: acceleratedNetwork + } + } +} + +resource disk_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${disk.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: disk +} + +module disk_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AvSet-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: disk.id + } +}] + +@description('The resource group the disk was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the disk') +output resourceId string = disk.id + +@description('The name of the disk') +output name string = disk.name diff --git a/carml/1.0.0/Microsoft.Compute/disks/readme.md b/carml/1.0.0/Microsoft.Compute/disks/readme.md new file mode 100644 index 000000000..1953fa2e6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/readme.md @@ -0,0 +1,95 @@ +# Compute Disks `[Microsoft.Compute/disks]` + +This template deploys a disk + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/disks` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `acceleratedNetwork` | bool | | | Optional. True if the image from which the OS disk is created supports accelerated networking. | +| `burstingEnabled` | bool | | | Optional. Set to true to enable bursting beyond the provisioned performance target of the disk. | +| `completionPercent` | int | `100` | | Optional. Percentage complete for the background copy when a resource is created via the CopyStart operation. | +| `createOption` | string | `Empty` | `[Attach, Copy, CopyStart, Empty, FromImage, Import, ImportSecure, Restore, Upload, UploadPreparedSecure]` | Optional. Sources of a disk creation. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diskIOPSReadWrite` | int | | | Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks. | +| `diskMBpsReadWrite` | int | | | Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks. | +| `diskSizeGB` | int | | | Optional. If create option is empty, this field is mandatory and it indicates the size of the disk to create. | +| `hyperVGeneration` | string | `V2` | `[V1, V2]` | Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. | +| `imageReferenceId` | string | | | Optional. A relative uri containing either a Platform Image Repository or user image reference. | +| `location` | string | `[resourceGroup().location]` | | Optional. Resource location. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logicalSectorSize` | int | `4096` | | Optional. Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096. | +| `maxShares` | int | `1` | | Optional. The maximum number of VMs that can attach to the disk at the same time. Default value is 0. | +| `name` | string | | | Required. The name of the disk that is being created. | +| `networkAccessPolicy` | string | `DenyAll` | `[AllowAll, AllowPrivate, DenyAll]` | Optional. Policy for accessing the disk via network. | +| `osType` | string | | `[Windows, Linux, ]` | Optional. Sources of a disk creation. | +| `publicNetworkAccess` | string | `Disabled` | `[Disabled, Enabled]` | Optional. Policy for controlling export on the disk. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityDataUri` | string | | | Optional. If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state. | +| `sku` | string | | `[Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS, Premium_ZRS, Premium_ZRS]` | Required. The disks sku name. Can be . | +| `sourceResourceId` | string | | | Optional. If create option is Copy, this is the ARM ID of the source snapshot or disk. | +| `sourceUri` | string | | | Optional. If create option is Import, this is the URI of a blob to be imported into a managed disk. | +| `storageAccountId` | string | | | Optional. Required if create option is Import. The Azure Resource Manager identifier of the storage account containing the blob to import as a disk | +| `tags` | object | `{object}` | | Optional. Tags of the availability set resource. | +| `uploadSizeBytes` | int | `20972032` | | Optional. If create option is Upload, this is the size of the contents of the upload including the VHD footer. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disk | +| `resourceGroupName` | string | The resource group the disk was deployed into | +| `resourceId` | string | The resource ID of the disk | + +## Template references + +- [Disks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-08-01/disks) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Compute/disks/version.json b/carml/1.0.0/Microsoft.Compute/disks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/disks/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/carml/1.0.0/Microsoft.Compute/galleries/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/galleries/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..18ddea9d6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(gallery.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: gallery +}] diff --git a/carml/1.0.0/Microsoft.Compute/galleries/.parameters/images.parameters.json b/carml/1.0.0/Microsoft.Compute/galleries/.parameters/images.parameters.json new file mode 100644 index 000000000..78a802c19 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/.parameters/images.parameters.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsigweuimages001" + }, + "images": { + "value": [ + { + "name": "<>-az-imgd-x-003" + }, + { + "name": "<>-az-imgd-x-001", + "osType": "Windows", + "osState": "Generalized", + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2022-datacenter-azure-edition", + "minRecommendedvCPUs": 2, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "maxRecommendedMemory": 16, + "hyperVGeneration": "V1", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-imgd-x-002", + "osType": "Linux", + "osState": "Generalized", + "publisher": "canonical", + "offer": "0001-com-ubuntu-server-focal", + "sku": "20_04-lts-gen2", + "minRecommendedvCPUs": 1, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "maxRecommendedMemory": 32, + "hyperVGeneration": "V2" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/galleries/.parameters/parameters.json b/carml/1.0.0/Microsoft.Compute/galleries/.parameters/parameters.json new file mode 100644 index 000000000..ccacaf074 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsigweux001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/galleries/deploy.bicep b/carml/1.0.0/Microsoft.Compute/galleries/deploy.bicep new file mode 100644 index 000000000..7c6cac679 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/deploy.bicep @@ -0,0 +1,101 @@ +@minLength(1) +@description('Required. Name of the Azure Shared Image Gallery') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Description of the Azure Shared Image Gallery') +param galleryDescription string = '' + +@description('Optional. Images to create') +param images array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +module pidName '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' = { + name: name + location: location + tags: tags + properties: { + description: galleryDescription + identifier: {} + } +} + +resource gallery_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${gallery.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: gallery +} + +module gallery_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Gallery-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: gallery.id + } +}] + +// Images +module galleries_images 'images/deploy.bicep' = [for (image, index) in images: { + name: '${uniqueString(deployment().name, location)}-Gallery-Image-${index}' + params: { + name: image.name + galleryName: gallery.name + osType: contains(image, 'osType') ? image.osType : 'Windows' + osState: contains(image, 'osState') ? image.osState : 'Generalized' + publisher: contains(image, 'publisher') ? image.publisher : 'MicrosoftWindowsServer' + offer: contains(image, 'offer') ? image.offer : 'WindowsServer' + sku: contains(image, 'sku') ? image.sku : '2019-Datacenter' + minRecommendedvCPUs: contains(image, 'minRecommendedvCPUs') ? image.minRecommendedvCPUs : 1 + maxRecommendedvCPUs: contains(image, 'maxRecommendedvCPUs') ? image.maxRecommendedvCPUs : 4 + minRecommendedMemory: contains(image, 'minRecommendedMemory') ? image.minRecommendedMemory : 4 + maxRecommendedMemory: contains(image, 'maxRecommendedMemory') ? image.maxRecommendedMemory : 16 + hyperVGeneration: contains(image, 'hyperVGeneration') ? image.hyperVGeneration : 'V1' + /* imageDefinitionDescription: contains(image, 'imageDefinitionDescription') ? image.imageDefinitionDescription : '' + eula: contains(image, 'eula') ? image.eula : '' + privacyStatementUri: contains(image, 'privacyStatementUri') ? image.privacyStatementUri : '' + releaseNoteUri: contains(image, 'releaseNoteUri') ? image.releaseNoteUri : '' + productName: contains(image, 'productName') ? image.productName : '' + planName: contains(image, 'planName') ? image.planName : '' + planPublisherName: contains(image, 'planPublisherName') ? image.planPublisherName : '' + endOfLife: contains(image, 'endOfLife') ? image.endOfLife : '' + excludedDiskTypes: contains(image, 'excludedDiskTypes') ? image.excludedDiskTypes : [] */ + roleAssignments: contains(image, 'roleAssignments') ? image.roleAssignments : [] + tags: contains(image, 'tags') ? image.tags : {} + } +}] + +@description('The resource ID of the deployed image gallery') +output resourceId string = gallery.id + +@description('The resource group of the deployed image gallery') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed image gallery') +output name string = gallery.name diff --git a/carml/1.0.0/Microsoft.Compute/galleries/images/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/galleries/images/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/images/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..537bc8351 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'myCustomRoleAtSub': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3') +} + +resource galleryImage 'Microsoft.Compute/galleries/images@2020-09-30' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(galleryImage.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: galleryImage +}] diff --git a/carml/1.0.0/Microsoft.Compute/galleries/images/deploy.bicep b/carml/1.0.0/Microsoft.Compute/galleries/images/deploy.bicep new file mode 100644 index 000000000..5b2bc6b5d --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/images/deploy.bicep @@ -0,0 +1,165 @@ +@description('Required. Name of the image definition.') +param name string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Name of the Azure Shared Image Gallery') +@minLength(1) +param galleryName string + +@description('Optional. OS type of the image to be created.') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string = 'Windows' + +@description('Optional. This property allows the user to specify whether the virtual machines created under this image are \'Generalized\' or \'Specialized\'.') +@allowed([ + 'Generalized' + 'Specialized' +]) +param osState string = 'Generalized' + +@description('Optional. The name of the gallery Image Definition publisher.') +param publisher string = 'MicrosoftWindowsServer' + +@description('Optional. The name of the gallery Image Definition offer.') +param offer string = 'WindowsServer' + +@description('Optional. The name of the gallery Image Definition SKU.') +param sku string = '2019-Datacenter' + +@description('Optional. The minimum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param minRecommendedvCPUs int = 1 + +@description('Optional. The maximum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param maxRecommendedvCPUs int = 4 + +@description('Optional. The minimum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param minRecommendedMemory int = 4 + +@description('Optional. The maximum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param maxRecommendedMemory int = 16 + +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2') +@allowed([ + 'V1' + 'V2' +]) +param hyperVGeneration string = 'V1' +/* +@description('Optional. The description of this gallery Image Definition resource. This property is updatable.') +param imageDefinitionDescription string = '' + +@description('Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL.') +param eula string = '' + +@description('Optional. The privacy statement uri. Has to be a valid URL.') +param privacyStatementUri string = '' + +@description('Optional. The release note uri. Has to be a valid URL.') +param releaseNoteUri string = '' + +@description('Optional. The product ID.') +param productName string = '' + +@description('Optional. The plan ID.') +param planName string = '' + +@description('Optional. The publisher ID.') +param planPublisherName string = '' + +@description('Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z') +param endOfLife string = '' + +@description('Optional. List of the excluded disk types. E.g. Standard_LRS') +param excludedDiskTypes array = [] +*/ +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for all resources.') +param tags object = {} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' existing = { + name: galleryName +} + +resource image 'Microsoft.Compute/galleries/images@2020-09-30' = { + name: name + parent: gallery + location: location + tags: tags + properties: { + osType: osType + osState: osState + identifier: { + publisher: publisher + offer: offer + sku: sku + } + recommended: { + vCPUs: { + min: minRecommendedvCPUs + max: maxRecommendedvCPUs + } + memory: { + min: minRecommendedMemory + max: maxRecommendedMemory + } + } + hyperVGeneration: hyperVGeneration + + /// Options below break the VM creation from Image Gallery. Therefore, it's commented out for AVD + + /* description: imageDefinitionDescription + eula: eula + privacyStatementUri: privacyStatementUri + releaseNoteUri: releaseNoteUri + purchasePlan: { + product: !empty(productName) ? productName : null + name: !empty(planName) ? planName : null + publisher: !empty(planPublisherName) ? planPublisherName : null + } + endOfLifeDate: endOfLife + disallowed: { + diskTypes: excludedDiskTypes + } */ + } +} + +module galleryImage_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: image.id + } +}] + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the image') +output resourceId string = image.id + +@description('The name of the image') +output name string = image.name diff --git a/carml/1.0.0/Microsoft.Compute/galleries/images/imageDefinition.bicep b/carml/1.0.0/Microsoft.Compute/galleries/images/imageDefinition.bicep new file mode 100644 index 000000000..7a287977a --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/images/imageDefinition.bicep @@ -0,0 +1,88 @@ +param imageDefinitionPropertiesName object +param location string +param SIGname string +@description('Optional. OS type of the image to be created.') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string = 'Windows' + +@description('Optional. This property allows the user to specify whether the virtual machines created under this image are \'Generalized\' or \'Specialized\'.') +@allowed([ + 'Generalized' + 'Specialized' +]) +param osState string = 'Generalized' + +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2') +@allowed([ + 'V1' + 'V2' +]) +param hyperVGeneration string = 'V1' + +@description('Optional. The name of the gallery Image Definition publisher.') +param publisher string = 'MicrosoftWindowsServer' + +@description('Optional. The name of the gallery Image Definition offer.') +param offer string = 'WindowsServer' + +@description('Optional. The name of the gallery Image Definition SKU.') +param sku string = '2019-Datacenter' + +@description('Optional. The minimum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param minRecommendedvCPUs int = 1 + +@description('Optional. The maximum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param maxRecommendedvCPUs int = 4 + +@description('Optional. The minimum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param minRecommendedMemory int = 4 + +@description('Optional. The maximum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param maxRecommendedMemory int = 16 + +var ImageDefinitionName = '${SIGname}/${imageDefinitionPropertiesName}' + +resource imageDefinition 'Microsoft.Compute/galleries/images@2020-09-30' = { + name: ImageDefinitionName + location: location + properties: { + osType: 'Windows' + osState: 'Generalized' + identifier: { + publisher: publisher + offer: offer + sku: sku + } + recommended: { + vCPUs: { + min: minRecommendedvCPUs + max: maxRecommendedvCPUs + } + memory: { + min: minRecommendedMemory + max: maxRecommendedMemory + } + } + hyperVGeneration: hyperVGeneration + } +} + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the image') +output resourceId string = imageDefinition.id + +@description('The name of the image') +output name string = imageDefinition.name diff --git a/carml/1.0.0/Microsoft.Compute/galleries/images/readme.md b/carml/1.0.0/Microsoft.Compute/galleries/images/readme.md new file mode 100644 index 000000000..916fab525 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/images/readme.md @@ -0,0 +1,92 @@ +# Shared Image Definition `[Microsoft.Compute/galleries/images]` + +This module deploys an Image Definition in a Shared Image Gallery. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/galleries/images` | 2020-09-30 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `endOfLife` | string | | | Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z | +| `eula` | string | | | Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL. | +| `excludedDiskTypes` | array | `[]` | | Optional. List of the excluded disk types. E.g. Standard_LRS | +| `galleryName` | string | | | Required. Name of the Azure Shared Image Gallery | +| `hyperVGeneration` | string | `V1` | `[V1, V2]` | Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2 | +| `imageDefinitionDescription` | string | | | Optional. The description of this gallery Image Definition resource. This property is updatable. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `maxRecommendedMemory` | int | `16` | | Optional. The maximum amount of RAM in GB recommended for this image. | +| `maxRecommendedvCPUs` | int | `4` | | Optional. The maximum number of the CPU cores recommended for this image. | +| `minRecommendedMemory` | int | `4` | | Optional. The minimum amount of RAM in GB recommended for this image. | +| `minRecommendedvCPUs` | int | `1` | | Optional. The minimum number of the CPU cores recommended for this image. | +| `name` | string | | | Required. Name of the image definition. | +| `offer` | string | `WindowsServer` | | Optional. The name of the gallery Image Definition offer. | +| `osState` | string | `Generalized` | `[Generalized, Specialized]` | Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'. | +| `osType` | string | `Windows` | `[Windows, Linux]` | Optional. OS type of the image to be created. | +| `planName` | string | | | Optional. The plan ID. | +| `planPublisherName` | string | | | Optional. The publisher ID. | +| `privacyStatementUri` | string | | | Optional. The privacy statement uri. Has to be a valid URL. | +| `productName` | string | | | Optional. The product ID. | +| `publisher` | string | `MicrosoftWindowsServer` | | Optional. The name of the gallery Image Definition publisher. | +| `releaseNoteUri` | string | | | Optional. The release note uri. Has to be a valid URL. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `2019-Datacenter` | | Optional. The name of the gallery Image Definition SKU. | +| `tags` | object | `{object}` | | Optional. Tags for all resources. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image | +| `resourceGroupName` | string | The resource group the image was deployed into | +| `resourceId` | string | The resource ID of the image | + +## Template references + +- [Galleries/Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries/images) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Compute/galleries/images/version.json b/carml/1.0.0/Microsoft.Compute/galleries/images/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/images/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/carml/1.0.0/Microsoft.Compute/galleries/readme.md b/carml/1.0.0/Microsoft.Compute/galleries/readme.md new file mode 100644 index 000000000..6086b7d95 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/readme.md @@ -0,0 +1,79 @@ +# Azure Compute Galleries `[Microsoft.Compute/galleries]` + +This module deploys an Azure compute gallery (formerly known as shared image gallery). + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/galleries` | 2020-09-30 | +| `Microsoft.Compute/galleries/images` | 2020-09-30 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `galleryDescription` | string | | | Optional. Description of the Azure Shared Image Gallery | +| `images` | _[images](images/readme.md)_ array | `[]` | | Optional. Images to create | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the Azure Shared Image Gallery | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags for all resources. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed image gallery | +| `resourceGroupName` | string | The resource group of the deployed image gallery | +| `resourceId` | string | The resource ID of the deployed image gallery | + +## Template references + +- [Galleries](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries) +- [Galleries/Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries/images) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Compute/galleries/version.json b/carml/1.0.0/Microsoft.Compute/galleries/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/galleries/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/carml/1.0.0/Microsoft.Compute/images/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/images/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/images/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/images/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/images/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..aa3a3fa03 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/images/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'myCustomRoleAtSub': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3') +} + +resource image 'Microsoft.Compute/images@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(image.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: image +}] diff --git a/carml/1.0.0/Microsoft.Compute/images/.parameters/parameters.json b/carml/1.0.0/Microsoft.Compute/images/.parameters/parameters.json new file mode 100644 index 000000000..85e8b306e --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/images/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-img-x-001" + }, + "osAccountType": { + "value": "Premium_LRS" + }, + "osType": { + "value": "Windows" + }, + "osDiskBlobUri": { + "value": "https://adp<>azsax001.blob.core.windows.net/vhds/adp-<>-az-imgt-x-001.vhd" + }, + "osDiskCaching": { + "value": "ReadWrite" + }, + "zoneResilient": { + "value": true + }, + "hyperVGeneration": { + "value": "V1" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/images/deploy.bicep b/carml/1.0.0/Microsoft.Compute/images/deploy.bicep new file mode 100644 index 000000000..f17102d68 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/images/deploy.bicep @@ -0,0 +1,74 @@ +@description('Required. The name of the image.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The Virtual Hard Disk.') +param osDiskBlobUri string + +@description('Required. This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux') +param osType string + +@description('Optional. Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite') +param osDiskCaching string + +@description('Optional. Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS') +param osAccountType string + +@description('Optional. Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS).') +param zoneResilient bool = false + +@description('Optional. Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2') +param hyperVGeneration string = 'V1' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 image 'Microsoft.Compute/images@2021-04-01' = { + name: name + location: location + tags: tags + properties: { + storageProfile: { + osDisk: { + osType: osType + blobUri: osDiskBlobUri + caching: osDiskCaching + storageAccountType: osAccountType + } + dataDisks: [] + zoneResilient: zoneResilient + } + hyperVGeneration: hyperVGeneration + } +} + +module image_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Image-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: image.id + } +}] + +@description('The resource ID of the image') +output resourceId string = image.id + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image') +output name string = image.name diff --git a/carml/1.0.0/Microsoft.Compute/images/readme.md b/carml/1.0.0/Microsoft.Compute/images/readme.md new file mode 100644 index 000000000..21c3e1a47 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/images/readme.md @@ -0,0 +1,78 @@ +# Images `[Microsoft.Compute/images]` + +This module deploys a compute image. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/images` | 2021-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `hyperVGeneration` | string | `V1` | | Optional. Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2 | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | | | Required. The name of the image. | +| `osAccountType` | string | | | Optional. Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS | +| `osDiskBlobUri` | string | | | Required. The Virtual Hard Disk. | +| `osDiskCaching` | string | | | Optional. Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite | +| `osType` | string | | | Required. This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `zoneResilient` | bool | | | Optional. Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS). | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image | +| `resourceGroupName` | string | The resource group the image was deployed into | +| `resourceId` | string | The resource ID of the image | + +## Template references + +- [Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/images) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Compute/images/version.json b/carml/1.0.0/Microsoft.Compute/images/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/images/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/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b4f7f380f --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,38 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(proximityPlacementGroup.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: proximityPlacementGroup +}] diff --git a/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json new file mode 100644 index 000000000..71bff3e25 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ppg-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/deploy.bicep b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/deploy.bicep new file mode 100644 index 000000000..0c215b8fd --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. The name of the proximity placement group that is being created.') +param name string = '' + +@description('Optional. Specifies the type of the proximity placement group.') +@allowed([ + 'Standard' + 'Ultra' +]) +param proximityPlacementGroupType string = 'Standard' + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the proximity placement group resource.') +param tags object = {} + +@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 proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' = { + name: name + location: location + tags: tags + properties: { + proximityPlacementGroupType: proximityPlacementGroupType + } +} + +resource proximityPlacementGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${proximityPlacementGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: proximityPlacementGroup +} + +module proximityPlacementGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ProxPlaceGroup-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: proximityPlacementGroup.id + } +}] + +@description('The name of the proximity placement group') +output name string = proximityPlacementGroup.name + +@description('The resourceId the proximity placement group') +output resourceId string = proximityPlacementGroup.id + +@description('The resource group the proximity placement group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/readme.md b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/readme.md new file mode 100644 index 000000000..3f4fb2086 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/readme.md @@ -0,0 +1,76 @@ +# Proximity Placement Groups `[Microsoft.Compute/proximityPlacementGroups]` + +This template deploys a proximity placement group. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/proximityPlacementGroups` | 2021-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Resource location. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the proximity placement group that is being created. | +| `proximityPlacementGroupType` | string | `Standard` | `[Standard, Ultra]` | Optional. Specifies the type of the proximity placement group. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the proximity placement group resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the proximity placement group | +| `resourceGroupName` | string | The resource group the proximity placement group was deployed into | +| `resourceId` | string | The resourceId the proximity placement group | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Proximityplacementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/proximityPlacementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/version.json b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/proximityPlacementGroups/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/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6648bea36 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(vmss.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: vmss +}] diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json new file mode 100644 index 000000000..0c3f3189b --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-linux-min-001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "skuName": { + "value": "Standard_B2s" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "adminUsername": { + "value": "scaleSetAdmin" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/scaleSetAdmin/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json new file mode 100644 index 000000000..b4d6340af --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json @@ -0,0 +1,186 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-linux-001" + }, + "vmNamePrefix": { + "value": "vmsslinvm" + }, + "skuName": { + "value": "Standard_B2s" + }, + "skuCapacity": { + "value": 1 + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmPriority": { + "value": "Regular" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "availabilityZones": { + "value": [ + "2" + ] + }, + "scaleSetFaultDomain": { + "value": 1 + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "bootDiagnosticStorageAccountName": { + "value": "adp<>azsax001" + }, + "osType": { + "value": "Linux" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "adminUsername": { + "value": "scaleSetAdmin" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/scaleSetAdmin/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "dataDisks": { + "value": [ + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "sudo apt-get update" + } + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json new file mode 100644 index 000000000..5444ff795 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-win-min-001" + }, + "skuName": { + "value": "Standard_B2s" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "adminUsername": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminUsername" + } + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json new file mode 100644 index 000000000..1fec6b76b --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json @@ -0,0 +1,182 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-win-001" + }, + "vmNamePrefix": { + "value": "vmsswinvm" + }, + "skuName": { + "value": "Standard_B2s" + }, + "skuCapacity": { + "value": 1 + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmPriority": { + "value": "Regular" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "adminUsername": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminUsername" + } + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep new file mode 100644 index 000000000..f807c6218 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep @@ -0,0 +1,650 @@ +@description('Required. Name of the VMSS.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Fault Domain count for each placement group.') +param scaleSetFaultDomain int = 2 + +@description('Optional. Creates an proximity placement group and adds the VMs to it.') +param proximityPlacementGroupName string = '' + +@description('Optional. Specifies the type of the proximity placement group.') +@allowed([ + 'Standard' + 'Ultra' +]) +param proximityPlacementGroupType string = 'Standard' + +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Specifies the mode of an upgrade to virtual machines in the scale set.\' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling') +@allowed([ + 'Manual' + 'Automatic' + 'Rolling' +]) +param upgradePolicyMode string = 'Manual' + +@description('Optional. The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability.') +param maxBatchInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch') +param maxUnhealthyInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch.') +param maxUnhealthyUpgradedInstancePercent int = 20 + +@description('Optional. The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format') +param pauseTimeBetweenBatches string = 'PT0S' + +@description('Optional. Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true.') +param enableAutomaticOSUpgrade bool = false + +@description('Optional. Whether OS image rollback feature should be disabled.') +param disableAutomaticRollback bool = false + +@description('Optional. Specifies whether automatic repairs should be enabled on the virtual machine scale set.') +param automaticRepairsPolicyEnabled bool = false + +@description('Optional. The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M).') +param gracePeriod string = 'PT30M' + +@description('Optional. Specifies the computer name prefix for all of the virtual machines in the scale set.') +@minLength(1) +@maxLength(15) +param vmNamePrefix string = 'vmssvm' + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machines in the scale set.') +param secrets array = [] + +@description('Optional. Specifies Scheduled Event related configurations') +param scheduledEventsProfile object = {} + +@description('Optional. Specifies whether the Virtual Machine Scale Set should be overprovisioned.') +param overprovision bool = false + +@description('Optional. When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs.') +param doNotRunExtensionsOnOverprovisionedVMs bool = false + +@description('Optional. Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage.') +param zoneBalance bool = false + +@description('Optional. When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true.') +param singlePlacementGroup bool = true + +@description('Optional. Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in') +param scaleInPolicy object = { + rules: [ + 'Default' + ] +} + +@description('Required. The SKU size of the VMs.') +param skuName string + +@description('Optional. The initial instance count of scale set VMs.') +param skuCapacity int = 1 + +@description('Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set.') +param availabilityZones array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' = if (!empty(proximityPlacementGroupName)) { + name: !empty(proximityPlacementGroupName) ? proximityPlacementGroupName : 'dummyProximityGroup' + location: location + tags: tags + properties: { + proximityPlacementGroupType: proximityPlacementGroupType + } +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: identity + zones: availabilityZones + properties: { + proximityPlacementGroup: !empty(proximityPlacementGroupName) ? { + id: az.resourceId('Microsoft.Compute/proximityPlacementGroups', proximityPlacementGroup.name) + } : null + upgradePolicy: { + mode: upgradePolicyMode + rollingUpgradePolicy: { + maxBatchInstancePercent: maxBatchInstancePercent + maxUnhealthyInstancePercent: maxUnhealthyInstancePercent + maxUnhealthyUpgradedInstancePercent: maxUnhealthyUpgradedInstancePercent + pauseTimeBetweenBatches: pauseTimeBetweenBatches + } + automaticOSUpgradePolicy: { + enableAutomaticOSUpgrade: enableAutomaticOSUpgrade + disableAutomaticRollback: disableAutomaticRollback + } + } + automaticRepairsPolicy: { + enabled: automaticRepairsPolicyEnabled + gracePeriod: gracePeriod + } + virtualMachineProfile: { + osProfile: { + computerNamePrefix: vmNamePrefix + adminUsername: adminUsername + adminPassword: !empty(adminPassword) ? adminPassword : null + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: secrets + } + securityProfile: { + encryptionAtHost: encryptionAtHost + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + + } + storageProfile: { + imageReference: imageReference + osDisk: { + createOption: osDisk.createOption + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : null + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + diffDiskSettings: contains(osDisk, 'diffDiskSettings') ? osDisk.diffDiskSettings : null + osType: contains(osDisk, 'osType') ? osDisk.osType : null + image: contains(osDisk, 'image') ? osDisk.image : null + vhdContainers: contains(osDisk, 'vhdContainers') ? osDisk.vhdContainers : null + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? osDisk.managedDisk.diskEncryptionSet : null + } + } + dataDisks: [for (item, j) in dataDisks: { + lun: j + diskSizeGB: item.diskSizeGB + createOption: item.createOption + caching: item.caching + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + managedDisk: { + storageAccountType: item.managedDisk.storageAccountType + diskEncryptionSet: { + id: enableServerSideEncryption ? item.managedDisk.diskEncryptionSet.id : null + } + } + diskIOPSReadWrite: contains(osDisk, 'diskIOPSReadWrite') ? item.diskIOPSReadWrite : null + diskMBpsReadWrite: contains(osDisk, 'diskMBpsReadWrite') ? item.diskMBpsReadWrite : null + }] + } + networkProfile: { + networkInterfaceConfigurations: [for (nicConfiguration, index) in nicConfigurations: { + name: '${name}${nicConfiguration.nicSuffix}configuration-${index}' + properties: { + primary: (index == 0) ? true : any(null) + enableAcceleratedNetworking: contains(nicConfigurations, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : null + networkSecurityGroup: contains(nicConfigurations, 'nsgId') ? { + id: nicConfiguration.nsgId + } : null + ipConfigurations: nicConfiguration.ipConfigurations + } + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + licenseType: empty(licenseType) ? null : licenseType + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? json('{"maxPrice":"${maxPriceForLowPriorityVm}"}') : null + scheduledEventsProfile: scheduledEventsProfile + } + overprovision: overprovision + doNotRunExtensionsOnOverprovisionedVMs: doNotRunExtensionsOnOverprovisionedVMs + zoneBalance: zoneBalance == 'true' ? zoneBalance : null + platformFaultDomainCount: scaleSetFaultDomain + singlePlacementGroup: singlePlacementGroup + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + scaleInPolicy: scaleInPolicy + } + sku: { + name: skuName + capacity: skuCapacity + } + plan: !empty(plan) ? plan : null +} + +module vmss_domainJoinExtension 'extensions/deploy.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DomainJoin' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + } +} + +module vmss_microsoftAntiMalwareExtension 'extensions/deploy.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftAntiMalware' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + } +} + +resource vmss_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split(monitoringWorkspaceId, '/')) + scope: resourceGroup(split(monitoringWorkspaceId, '/')[2], split(monitoringWorkspaceId, '/')[4]) +} + +module vmss_microsoftMonitoringAgentExtension 'extensions/deploy.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftMonitoringAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftMonitoringAgent' + publisher: 'Microsoft.EnterpriseCloud.Monitoring' + type: osType == 'Windows' ? 'MicrosoftMonitoringAgent' : 'OmsAgentForLinux' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.7') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vmss_logAnalyticsWorkspace.id, vmss_logAnalyticsWorkspace.apiVersion).customerId : '' + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vmss_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + } +} + +module vmss_dependencyAgentExtension 'extensions/deploy.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DependencyAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + } +} + +module vmss_networkWatcherAgentExtension 'extensions/deploy.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-NetworkWatcherAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + } +} + +module vmss_desiredStateConfigurationExtension 'extensions/deploy.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DesiredStateConfiguration' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } +} + +module vmss_customScriptExtension 'extensions/deploy.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-CustomScriptExtension' + params: { + virtualMachineScaleSetName: vmss.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') ? extensionCustomScriptConfig.protectedSettings : {} + } + dependsOn: [ + vmss_desiredStateConfigurationExtension + ] +} + +module vmss_diskEncryptionExtension 'extensions/deploy.bicep' = if (extensionDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DiskEncryption' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionDiskEncryptionConfig, 'typeHandlerVersion') ? extensionDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionDiskEncryptionConfig, 'forceUpdateTag') ? extensionDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionDiskEncryptionConfig.settings + } + dependsOn: [ + vmss_customScriptExtension + vmss_microsoftMonitoringAgentExtension + ] +} + +resource vmss_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vmss.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vmss +} + +resource vmss_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${vmss.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: vmss +} + +module vmss_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VMSS-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: vmss.id + } +}] + +@description('The resource ID of the virtual machine scale set') +output resourceId string = vmss.id + +@description('The resource group of the virtual machine scale set') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual machine scale set') +output name string = vmss.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(vmss.identity, 'principalId') ? vmss.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep new file mode 100644 index 000000000..85d0e125d --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. The name of the virtual machine scale set that extension is provisioned for') +param virtualMachineScaleSetName string + +@description('Required. The name of the virtual machine scale set extension') +param name string + +@description('Required. The name of the extension handler publisher') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension"') +param type string + +@description('Required. Specifies the version of the script handler') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available') +param enableAutomaticUpgrade bool + +@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 virtualMachineScaleSet 'Microsoft.Compute/virtualMachineScaleSets@2021-07-01' existing = { + name: virtualMachineScaleSetName +} + +resource extension 'Microsoft.Compute/virtualMachineScaleSets/extensions@2021-07-01' = { + name: name + parent: virtualMachineScaleSet + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The ResourceId of the extension') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md new file mode 100644 index 000000000..d0d65b2b7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md @@ -0,0 +1,38 @@ +# virtual machine scale set Extensions `[Microsoft.Compute/virtualMachineScaleSets/extensions]` + +This module deploys a virtual machine scale set extension. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | 2021-07-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `autoUpgradeMinorVersion` | bool | | | Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true | +| `cuaId` | string | | | Optional. Customer Usage Attribution id (GUID). This GUID must be previously registered | +| `enableAutomaticUpgrade` | bool | | | Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available | +| `forceUpdateTag` | string | | | Optional. How the extension handler should be forced to update even if the extension configuration has not changed | +| `name` | string | | | Required. The name of the virtual machine scale set extension | +| `protectedSettings` | secureObject | `{object}` | | Optional. Any object that contains the extension specific protected settings | +| `publisher` | string | | | Required. The name of the extension handler publisher | +| `settings` | object | `{object}` | | Optional. Any object that contains the extension specific settings | +| `supressFailures` | bool | | | Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false | +| `type` | string | | | Required. Specifies the type of the extension; an example is "CustomScriptExtension" | +| `typeHandlerVersion` | string | | | Required. Specifies the version of the script handler | +| `virtualMachineScaleSetName` | string | | | Required. The name of the virtual machine scale set that extension is provisioned for | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The ResourceId of the extension | + +## Template references + +- [Virtualmachinescalesets/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachineScaleSets/extensions) diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/version.json b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/extensions/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/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/readme.md b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/readme.md new file mode 100644 index 000000000..f4de5c1b0 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/readme.md @@ -0,0 +1,438 @@ +# Virtual Machine Scale Sets `[Microsoft.Compute/virtualMachineScaleSets]` + +This module deploys a virtual machine scale set. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/proximityPlacementGroups` | 2021-04-01 | +| `Microsoft.Compute/virtualMachineScaleSets` | 2021-04-01 | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | 2021-07-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.Network/VirtualNetwork` + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | | | Optional. When specifying a Windows Virtual Machine, this value should be passed | +| `adminUsername` | secureString | | | Required. Administrator username | +| `automaticRepairsPolicyEnabled` | bool | | | Optional. Specifies whether automatic repairs should be enabled on the virtual machine scale set. | +| `availabilityZones` | array | `[]` | | Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set. | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a registration token. | +| `bootDiagnosticStorageAccountName` | string | | | Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Optional. Storage account boot diagnostic base URI. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customData` | string | | | Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `disableAutomaticRollback` | bool | | | Optional. Whether OS image rollback feature should be disabled. | +| `disablePasswordAuthentication` | bool | | | Optional. Specifies whether password authentication should be disabled. | +| `doNotRunExtensionsOnOverprovisionedVMs` | bool | | | Optional. When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs. | +| `enableAutomaticOSUpgrade` | bool | | | Optional. Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true. | +| `enableAutomaticUpdates` | bool | `True` | | Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableEvictionPolicy` | bool | | | Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | | | Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine scale set. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| `extensionAntiMalwareConfig` | object | `{object}` | | Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDependencyAgentConfig` | object | `{object}` | | Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | | | Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `gracePeriod` | string | `PT30M` | | Optional. The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M). | +| `imageReference` | object | | | Required. OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `licenseType` | string | | `[Windows_Client, Windows_Server, ]` | Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `maxBatchInstancePercent` | int | `20` | | Optional. The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability. | +| `maxPriceForLowPriorityVm` | string | | | Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `maxUnhealthyInstancePercent` | int | `20` | | Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch | +| `maxUnhealthyUpgradedInstancePercent` | int | `20` | | Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `monitoringWorkspaceId` | string | | | Optional. Resource ID of the monitoring log analytics workspace. | +| `name` | string | | | Required. Name of the VMSS. | +| `nicConfigurations` | array | `[]` | | Required. Configures NICs and PIPs. | +| `osDisk` | object | | | Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.| +| `osType` | string | | `[Windows, Linux]` | Required. The chosen OS type | +| `overprovision` | bool | | | Optional. Specifies whether the Virtual Machine Scale Set should be overprovisioned. | +| `pauseTimeBetweenBatches` | string | `PT0S` | | Optional. The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format | +| `plan` | object | `{object}` | | Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | | | Optional. Creates an proximity placement group and adds the VMs to it. | +| `proximityPlacementGroupType` | string | `Standard` | `[Standard, Ultra]` | Optional. Specifies the type of the proximity placement group. | +| `publicKeys` | array | `[]` | | Optional. The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sasTokenValidityLength` | string | `PT8H` | | Optional. SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `scaleInPolicy` | object | `{object}` | | Optional. Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in | +| `scaleSetFaultDomain` | int | `2` | | Optional. Fault Domain count for each placement group. | +| `scheduledEventsProfile` | object | `{object}` | | Optional. Specifies Scheduled Event related configurations | +| `secrets` | array | `[]` | | Optional. Specifies set of certificates that should be installed onto the virtual machines in the scale set. | +| `securityType` | string | | `TrustedLaunch` | Optional. Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings. | +| `secureBootEnabled` | bool | `False` | | Optional. Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `singlePlacementGroup` | bool | `True` | | Optional. When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true. | +| `skuCapacity` | int | `1` | | Optional. The initial instance count of scale set VMs. | +| `skuName` | string | | | Required. The SKU size of the VMs. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `timeZone` | string | | | Optional. Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be 'TimeZoneInfo.id' value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | | | Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `upgradePolicyMode` | string | `Manual` | `[Manual, Automatic, Rolling]` | Optional. Specifies the mode of an upgrade to virtual machines in the scale set.' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `vmNamePrefix` | string | `vmssvm` | | Optional. Specifies the computer name prefix for all of the virtual machines in the scale set. | +| `vmPriority` | string | `Regular` | `[Regular, Low, Spot]` | Optional. Specifies the priority for the virtual machine. | +| `vTpmEnabled` | bool | `False` | | Optional. Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | +| `zoneBalance` | bool | | | Optional. Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage. | + +#### Marketplace images + +```json +"imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } +} +``` + +#### Custom images + +```json +"imageReference": { + "value": { + "id": "/subscriptions/12345-6789-1011-1213-15161718/resourceGroups/rg-name/providers/Microsoft.Compute/images/imagename" + } +} +``` + +### Parameter Usage: `plan` + +```json +"plan": { + "value": { + "name": "qvsa-25", + "product": "qualys-virtual-scanner", + "publisher": "qualysguard" + } +} +``` + +### Parameter Usage: `osDisk` + +```json + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { // Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. + "id": "/subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/" + } + } + } +} +``` + +### Parameter Usage: `dataDisks` + +```json +"dataDisks": { + "value": [{ + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "writeAcceleratorEnabled": true, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "writeAcceleratorEnabled": true, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }] +} +``` + +### Parameter Usage `nicConfigurations` + +```json +"nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/agents-vmss-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-scaleset/subnets/sxx-az-subnet-scaleset-linux" + } + } + } + ] + } + ] +} +``` + + +### Parameter Usage `extensionDomainJoinConfig` + + +```json +"windowsScriptExtensionFileData": { + "value": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageAccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageAccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + "secretName": "domainJoinUser-Password" + } +} +``` + +### Parameter Usage `extensionNetworkWatcherAgentConfig` + +```json +"extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } +} +``` + +### Parameter Usage: `microsoftAntiMalwareSettings` + +Only for OSType Windows + +```json +"extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } +} +``` + +### Parameter Usage: `extensionDiskEncryptionConfig` + +```json +"extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://mykeyvault.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionKeyURL": "https://mykeyvault.vault.azure.net/keys/keyEncryptionKey/3e13110def0d4a26ac38341c73c059bb", + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } +} +``` + +### Parameter Usage: `windowsScriptExtensionFileData` + +```json +"extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + //storage accounts with SAS token requirement + { + "uri": "https://<>.blob.core.windows.net/scripts/File1.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/WVD-Mgmt-TO-RG/providers/Microsoft.Storage/storageAccounts/wvdtoassetsstore" + }, + { + "uri": "https://<>.blob.core.windows.net/scripts/File2.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/WVD-Mgmt-TO-RG/providers/Microsoft.Storage/storageAccounts/wvdtoassetsstore" + }, + //storage account with public container (no SAS token is required) OR other public URL (not a storage account) + { + "uri": "https://github.com/myProject/File3.ps1" + } + ], + "protectedSettings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + } +} +``` + +### Parameter Usage: `windowsScriptExtensionFileData` with native storage account key support + +```json +"extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://<>.blob.core.windows.net/scripts/File1.ps1" + } + ], + "protectedSettings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"", + "cseStorageAccountName": "mystorageaccount", + "cseStorageAccountKey": "MyPlaceholder", + } + } +} +``` + +### Parameter Usage: `extensionDSCConfig` + +```json +"extensionDSCConfig": { + "value": { + "enabled": true, + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "http://validURLToConfigLocation", + "script": "ConfigurationScript.ps1", + "function": "ConfigurationFunction" + }, + "configurationArguments": { + "argument1": "Value1", + "argument2": "Value2" + }, + "configurationData": { + "url": "https://foo.psd1" + }, + "privacy": { + "dataCollection": "enable" + }, + "advancedOptions": { + "forcePullAndApply": false, + "downloadMappings": { + "specificDependencyKey": "https://myCustomDependencyLocation" + } + } + }, + "protectedSettings": { + "configurationArguments": { + "mySecret": "MyPlaceholder" + }, + "configurationUrlSasToken": "MyPlaceholder", + "configurationDataUrlSasToken": "MyPlaceholder" + } + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual machine scale set | +| `resourceGroupName` | string | The resource group of the virtual machine scale set | +| `resourceId` | string | The resource ID of the virtual machine scale set | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Proximityplacementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/proximityPlacementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualmachinescalesets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/virtualMachineScaleSets) +- [Virtualmachinescalesets/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachineScaleSets/extensions) diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/version.json b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachineScaleSets/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/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep new file mode 100644 index 000000000..7e6865bc6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep @@ -0,0 +1,27 @@ +param backupResourceName string + +@allowed([ + 'AzureFileShareProtectedItem' + 'AzureVmWorkloadSAPAseDatabase' + 'AzureVmWorkloadSAPHanaDatabase' + 'AzureVmWorkloadSQLDatabase' + 'DPMProtectedItem' + 'GenericProtectedItem' + 'MabFileFolderProtectedItem' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'Microsoft.Sql/servers/databases' +]) +param protectedItemType string +param backupPolicyId string +param sourceResourceId string + +resource backup 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2021-06-01' = { + name: backupResourceName + location: resourceGroup().location + properties: { + protectedItemType: protectedItemType + policyId: backupPolicyId + sourceResourceId: sourceResourceId + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep new file mode 100644 index 000000000..35df401f8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep @@ -0,0 +1,33 @@ +@description('Optional. The name of the configuration profile assignment') +param name string = 'default' + +@description('Required. The name of the VM to be associated') +param virtualMachineName string + +@description('Required. The configuration profile of automanage') +@allowed([ + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' +]) +param configurationProfile string + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: virtualMachineName +} + +resource configurationProfileAssignment 'Microsoft.Automanage/configurationProfileAssignments@2021-04-30-preview' = { + name: name + properties: { + configurationProfile: configurationProfile + } + scope: virtualMachine +} + +@description('The resource ID of the configuration profile assignment') +output resourceId string = configurationProfileAssignment.id + +@description('The name of the configuration profile assignment') +output name string = configurationProfileAssignment.name + +@description('The resource group the configuration profile assignment was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep new file mode 100644 index 000000000..4923abd80 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep @@ -0,0 +1,118 @@ +param networkInterfaceName string +param virtualMachineName string +param location string +param tags object +param enableIPForwarding bool = false +param enableAcceleratedNetworking bool = false +param dnsServers array = [] +param networkSecurityGroupId string = '' +param applicationSecurityGroupId string = '' +param ipConfigurationArray array +param lock string +param diagnosticStorageAccountId string +param diagnosticLogsRetentionInDays int +param diagnosticWorkspaceId string +param diagnosticEventHubAuthorizationRuleId string +param diagnosticEventHubName string +param pipMetricsToEnable array +param pipLogsToEnable array +param metricsToEnable array +param roleAssignments array + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module networkInterface_publicIPConfigurations 'nested_networkInterface_publicIPAddress.bicep' = [for (ipConfiguration, index) in ipConfigurationArray: if (contains(ipConfiguration, 'pipconfiguration')) { + name: '${deployment().name}-PIP-${index}' + params: { + publicIPAddressName: '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}' + publicIPPrefixId: (contains(ipConfiguration.pipconfiguration, 'publicIPPrefixId') ? (!(empty(ipConfiguration.pipconfiguration.publicIPPrefixId)) ? ipConfiguration.pipconfiguration.publicIPPrefixId : '') : '') + publicIPAllocationMethod: (contains(ipConfiguration.pipconfiguration, 'publicIPAllocationMethod') ? (!(empty(ipConfiguration.pipconfiguration.publicIPAllocationMethod)) ? ipConfiguration.pipconfiguration.publicIPAllocationMethod : 'Static') : 'Static') + skuName: (contains(ipConfiguration.pipconfiguration, 'skuName') ? (!(empty(ipConfiguration.pipconfiguration.skuName)) ? ipConfiguration.pipconfiguration.skuName : 'Standard') : 'Standard') + skuTier: (contains(ipConfiguration.pipconfiguration, 'skuTier') ? (!(empty(ipConfiguration.pipconfiguration.skuTier)) ? ipConfiguration.pipconfiguration.skuTier : 'Regional') : 'Regional') + location: location + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + metricsToEnable: pipMetricsToEnable + logsToEnable: pipLogsToEnable + lock: lock + roleAssignments: contains(ipConfiguration.pipconfiguration, 'roleAssignments') ? (!empty(ipConfiguration.pipconfiguration.roleAssignments) ? ipConfiguration.pipconfiguration.roleAssignments : []) : [] + tags: tags + } +}] + +resource networkInterface 'Microsoft.Network/networkInterfaces@2021-03-01' = { + name: networkInterfaceName + location: location + tags: tags + properties: { + enableIPForwarding: enableIPForwarding + enableAcceleratedNetworking: enableAcceleratedNetworking + dnsSettings: !empty(dnsServers) ? { + dnsServers: dnsServers + } : null + networkSecurityGroup: !empty(networkSecurityGroupId) ? { + id: networkSecurityGroupId + } : null + ipConfigurations: [for (ipConfiguration, index) in ipConfigurationArray: { + name: !empty(ipConfiguration.name) ? ipConfiguration.name : null + properties: { + primary: ((index == 0) ? true : false) + applicationSecurityGroups: !empty(applicationSecurityGroupId) ? [ + { + id: applicationSecurityGroupId + } + ] : null + privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) : null + privateIPAddress: contains(ipConfiguration, 'vmIPAddress') ? (!empty(ipConfiguration.vmIPAddress) ? ipConfiguration.vmIPAddress : null) : null + publicIPAddress: contains(ipConfiguration, 'pipconfiguration') ? json('{"id":"${resourceId('Microsoft.Network/publicIPAddresses', '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}')}"}') : null + subnet: { + id: ipConfiguration.subnetId + } + } + }] + } + dependsOn: [ + networkInterface_publicIPConfigurations + ] +} + +resource networkInterface_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkInterface.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkInterface +} + +resource networkInterface_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${networkInterface.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: networkInterface +} + +module networkInterface_rbac 'nested_networkInterface_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkInterface.id + } +}] diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep new file mode 100644 index 000000000..e12f5a8fb --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep @@ -0,0 +1,91 @@ +param publicIPAddressName string +param publicIPPrefixId string +param publicIPAllocationMethod string +param skuName string +param skuTier string +param location string +param diagnosticStorageAccountId string +param diagnosticLogsRetentionInDays int +param diagnosticWorkspaceId string +param diagnosticEventHubAuthorizationRuleId string +param diagnosticEventHubName string +param metricsToEnable array +param logsToEnable array +param lock string +param roleAssignments array +param tags object + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: publicIPAddressName + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + properties: { + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixId) ? { + id: publicIPPrefixId + } : null + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${publicIpAddress.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac 'nested_networkInterface_publicIPAddress_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The name of the resource group the public IP address was deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address.') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address.') +output resourceId string = publicIpAddress.id diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep new file mode 100644 index 000000000..a900d31e2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: publicIpAddress +}] diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep new file mode 100644 index 000000000..01a40acca --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource networkInterface 'Microsoft.Network/networkInterfaces@2021-03-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkInterface.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: networkInterface +}] diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ef0682440 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualMachine.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: virtualMachine +}] diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json new file mode 100644 index 000000000..051c53419 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-linux-min-01" + }, + "osType": { + "value": "Linux" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + } + } + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json new file mode 100644 index 000000000..6746a22b7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json @@ -0,0 +1,182 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-linux-01" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "osType": { + "value": "Linux" + }, + "encryptionAtHost": { + "value": false + }, + "availabilityZone": { + "value": 1 + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "backupVaultName": { + "value": "adp-<>-az-rsv-x-001" + }, + "backupVaultResourceGroup": { + "value": "validation-rg" + }, + "backupPolicyName": { + "value": "VMpolicy" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "monitoringWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": false + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "sudo apt-get update" + } + } + }, + "configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json new file mode 100644 index 000000000..f46d762dd --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "osType": { + "value": "Windows" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "adminUsername": { + "value": "localAdminUser" + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + } + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json new file mode 100644 index 000000000..ba7024125 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json @@ -0,0 +1,199 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-win-01" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "osType": { + "value": "Windows" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "availabilityZone": { + "value": 2 + }, + "adminUsername": { + "value": "localAdminUser" + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "backupVaultName": { + "value": "adp-<>-az-rsv-x-001" + }, + "backupVaultResourceGroup": { + "value": "validation-rg" + }, + "backupPolicyName": { + "value": "VMpolicy" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": "true", + "Exclusions": { + "Extensions": ".ext1;.ext2", + "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", + "Processes": "excludedproc1.exe;excludedproc2.exe" + }, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "monitoringWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + } + }, + "configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/deploy.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/deploy.bicep new file mode 100644 index 000000000..1ee9485bf --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/deploy.bicep @@ -0,0 +1,625 @@ +// Main resource +@description('Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group\'s name.') +param name string = take(toLower(uniqueString(resourceGroup().name)), 10) + +@description('Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are \'none\' (Default), \'uppercase\' and \'lowercase\'.') +param vmComputerNamesTransformation string = 'none' + +@description('Optional. Specifies the size for the VMs') +param vmSize string = 'Standard_D2s_v3' + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool + +@description('Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machine.') +param certificatesToBeInstalled array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies resource ID about the dedicated host that the virtual machine resides in.') +param dedicatedHostId string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Resource name of a proximity placement group.') +param proximityPlacementGroupName string = '' + +@description('Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set.') +param availabilitySetName string = '' + +//@description('Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set.') +@description('Optional. If the array is null then value would be set to 0 - no availability zones to be used. Must pass the zone leverage either pickZones function or pass down the array with zone number') +param availabilityZone array = [] + +// External resources +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param pipLogsToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param pipMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param nicMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. Recovery service vault name to add VMs to backup.') +param backupVaultName string = '' + +@description('Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default.') +param backupVaultResourceGroup string = resourceGroup().name + +@description('Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault.') +param backupPolicyName string = 'DefaultPolicy' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +// Child resources +@description('Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine.') +param allowExtensionOperations bool = true + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +// Shared parameters +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Any VM configuration profile assignments') +param configurationProfileAssignments array = [] + +var vmComputerNameTransformed = vmComputerNamesTransformation == 'uppercase' ? toUpper(name) : (vmComputerNamesTransformation == 'lowercase' ? toLower(name) : name) + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +module virtualMachine_nic '.bicep/nested_networkInterface.bicep' = [for (nicConfiguration, index) in nicConfigurations: { + name: '${uniqueString(deployment().name, location)}-VM-Nic-${index}' + params: { + networkInterfaceName: '${name}${nicConfiguration.nicSuffix}' + virtualMachineName: name + location: location + tags: tags + enableIPForwarding: contains(nicConfiguration, 'enableIPForwarding') ? (!empty(nicConfiguration.enableIPForwarding) ? nicConfiguration.enableIPForwarding : false) : false + enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true + dnsServers: contains(nicConfiguration, 'dnsServers') ? (!empty(nicConfiguration.dnsServers) ? nicConfiguration.dnsServers : []) : [] + networkSecurityGroupId: contains(nicConfiguration, 'nsgId') ? (!empty(nicConfiguration.nsgId) ? nicConfiguration.nsgId : '') : '' + applicationSecurityGroupId: contains(nicConfiguration, 'asgId') ? (!empty(nicConfiguration.asgId) ? nicConfiguration.asgId : '') : '' + ipConfigurationArray: nicConfiguration.ipConfigurations + lock: lock + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + metricsToEnable: nicMetricsToEnable + pipMetricsToEnable: pipMetricsToEnable + pipLogsToEnable: pipLogsToEnable + roleAssignments: contains(nicConfiguration, 'roleAssignments') ? (!empty(nicConfiguration.roleAssignments) ? nicConfiguration.roleAssignments : []) : [] + } +}] + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' = { + name: name + location: location + identity: identity + tags: tags + zones: availabilityZone == '' ? null : availabilityZone + plan: !empty(plan) ? plan : null + properties: { + hardwareProfile: { + vmSize: vmSize + } + securityProfile: encryptionAtHost ? { + encryptionAtHost: encryptionAtHost + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } : { + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + name: '${name}-disk-os-01' + createOption: osDisk.createOption + deleteOption: contains(osDisk, 'deleteOption') ? osDisk.deleteOption : 'Delete' + diskSizeGB: osDisk.diskSizeGB + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? osDisk.managedDisk.diskEncryptionSet : null + } + } + dataDisks: [for (dataDisk, index) in dataDisks: { + lun: index + name: '${name}-disk-data-${padLeft((index + 1), 2, '0')}' + diskSizeGB: dataDisk.diskSizeGB + createOption: dataDisk.createOption + deleteOption: contains(dataDisk, 'deleteOption') ? dataDisk.deleteOption : 'Delete' + caching: dataDisk.caching + managedDisk: { + storageAccountType: dataDisk.managedDisk.storageAccountType + diskEncryptionSet: { + id: enableServerSideEncryption ? dataDisk.managedDisk.diskEncryptionSet.id : null + } + } + }] + } + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + osProfile: { + computerName: vmComputerNameTransformed + adminUsername: adminUsername + adminPassword: adminPassword + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: certificatesToBeInstalled + allowExtensionOperations: allowExtensionOperations + } + networkProfile: { + networkInterfaces: [for (nicConfiguration, index) in nicConfigurations: { + properties: { + deleteOption: contains(nicConfiguration, 'deleteOption') ? nicConfiguration.deleteOption : 'Delete' + primary: index == 0 ? true : false + } + id: az.resourceId('Microsoft.Network/networkInterfaces', '${name}${nicConfiguration.nicSuffix}') + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + availabilitySet: !empty(availabilitySetName) ? json('{"id":"${az.resourceId('Microsoft.Compute/availabilitySets', availabilitySetName)}"}') : null + proximityPlacementGroup: !empty(proximityPlacementGroupName) ? json('{"id":"${az.resourceId('Microsoft.Compute/proximityPlacementGroups', proximityPlacementGroupName)}"}') : null + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? json('{"maxPrice":"${maxPriceForLowPriorityVm}"}') : null + host: !empty(dedicatedHostId) ? json('{"id":"${dedicatedHostId}"}') : null + licenseType: !empty(licenseType) ? licenseType : null + } + dependsOn: [ + virtualMachine_nic + ] +} + +module vm_configurationProfileAssignment '.bicep/nested_configurationProfileAssignment.bicep' = [for (configurationProfileAssignment, index) in configurationProfileAssignments: { + name: '${uniqueString(deployment().name, location)}-VM-ConfigurationProfileAssignment-${index}' + params: { + virtualMachineName: virtualMachine.name + configurationProfile: configurationProfileAssignment + } +}] + +module vm_domainJoinExtension 'extensions/deploy.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DomainJoin' + params: { + virtualMachineName: virtualMachine.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + } +} + +module vm_microsoftAntiMalwareExtension 'extensions/deploy.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftAntiMalware' + params: { + virtualMachineName: virtualMachine.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + } +} + +resource vm_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split(monitoringWorkspaceId, '/')) + scope: az.resourceGroup(split(monitoringWorkspaceId, '/')[2], split(monitoringWorkspaceId, '/')[4]) +} + +module vm_microsoftMonitoringAgentExtension 'extensions/deploy.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftMonitoringAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'MicrosoftMonitoringAgent' + publisher: 'Microsoft.EnterpriseCloud.Monitoring' + type: osType == 'Windows' ? 'MicrosoftMonitoringAgent' : 'OmsAgentForLinux' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.7') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vm_logAnalyticsWorkspace.id, vm_logAnalyticsWorkspace.apiVersion).customerId : '' + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vm_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + } +} + +module vm_dependencyAgentExtension 'extensions/deploy.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DependencyAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + } +} + +module vm_networkWatcherAgentExtension 'extensions/deploy.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-NetworkWatcherAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + } +} + +module vm_desiredStateConfigurationExtension 'extensions/deploy.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DesiredStateConfiguration' + params: { + virtualMachineName: virtualMachine.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.73' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } +} + +module vm_customScriptExtension 'extensions/deploy.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-CustomScriptExtension' + params: { + virtualMachineName: virtualMachine.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') ? extensionCustomScriptConfig.protectedSettings : {} + } + dependsOn: [ + vm_desiredStateConfigurationExtension + ] +} + +module vm_diskEncryptionExtension 'extensions/deploy.bicep' = if (extensionDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DiskEncryption' + params: { + virtualMachineName: virtualMachine.name + name: 'DiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionDiskEncryptionConfig, 'typeHandlerVersion') ? extensionDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionDiskEncryptionConfig, 'forceUpdateTag') ? extensionDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionDiskEncryptionConfig.settings + } + dependsOn: [ + vm_customScriptExtension + vm_microsoftMonitoringAgentExtension + ] +} + +module virtualMachine_backup '.bicep/nested_backup.bicep' = if (!empty(backupVaultName)) { + name: '${uniqueString(deployment().name, location)}-VM-Backup' + params: { + backupResourceName: '${backupVaultName}/Azure/iaasvmcontainer;iaasvmcontainerv2;${resourceGroup().name};${virtualMachine.name}/vm;iaasvmcontainerv2;${resourceGroup().name};${virtualMachine.name}' + protectedItemType: 'Microsoft.Compute/virtualMachines' + backupPolicyId: az.resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', backupVaultName, backupPolicyName) + sourceResourceId: virtualMachine.id + } + scope: az.resourceGroup(backupVaultResourceGroup) + dependsOn: [ + vm_domainJoinExtension + vm_microsoftMonitoringAgentExtension + vm_microsoftAntiMalwareExtension + vm_networkWatcherAgentExtension + vm_dependencyAgentExtension + vm_desiredStateConfigurationExtension + vm_customScriptExtension + ] +} + +resource virtualMachine_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualMachine.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualMachine +} + +module virtualMachine_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VM-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualMachine.id + } +}] + +@description('The name of the VM.') +output name string = virtualMachine.name + +@description('The resource ID of the VM.') +output resourceId string = virtualMachine.id + +@description('The name of the resource group the VM was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(virtualMachine.identity, 'principalId') ? virtualMachine.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-avd-session-hosts.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-avd-session-hosts.bicep new file mode 100644 index 000000000..a4fe34781 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-avd-session-hosts.bicep @@ -0,0 +1,32 @@ +param name string +param location string +param avdAgentPackageLocation string +param hostPoolName string +param systemData object = {} + + +//@secure() +param hostPoolToken string + +/* Add session hosts to Host Pool */ + +resource addToHostPool 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/Microsoft.PowerShell.DSC' + location: location + properties: { + publisher: 'Microsoft.PowerShell' + type: 'DSC' + typeHandlerVersion: '2.73' + autoUpgradeMinorVersion: true + settings: { + modulesUrl: avdAgentPackageLocation + configurationFunction: 'Configuration.ps1\\AddSessionHost' + properties: { + hostPoolName: hostPoolName + registrationInfoToken: hostPoolToken + aadJoin: false + sessionHostConfigurationLastUpdateTime: contains(systemData,'hostpoolUpdate') ? systemData.sessionHostConfigurationVersion : '' + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-azure-files-to-adds-script.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-azure-files-to-adds-script.bicep new file mode 100644 index 000000000..57fe7b040 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-azure-files-to-adds-script.bicep @@ -0,0 +1,22 @@ +param name string +param location string +param baseScriptUri string +param file string +@secure() +param ScriptArguments string + +resource addAzureFilesToADDSScript 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/addAzureFilesToADDSScript' + location: location + properties: { + publisher: 'Microsoft.Compute' + type: 'CustomScriptExtension' + typeHandlerVersion: '1.10' + autoUpgradeMinorVersion: true + settings: {} + protectedSettings: { + fileUris: array(baseScriptUri) + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File ${file} ${ScriptArguments}' + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-azure-files-to-adds.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-azure-files-to-adds.bicep new file mode 100644 index 000000000..129702d3b --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-azure-files-to-adds.bicep @@ -0,0 +1,46 @@ +param name string +param location string +param dscAgentPackageLocation string +param storageAccountName string +param storageAccountRG string +param domainName string +param AzureCloudEnvironment string + + + +@secure() +param domainAdminPassword string + +param domainAdminUsername string + +/* Add Azure Files to AD DS domain*/ + +resource addAzureFilesToADDS 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/Microsoft.PowerShell.DSC' + location: location + properties: { + publisher: 'Microsoft.PowerShell' + type: 'DSC' + typeHandlerVersion: '2.73' + autoUpgradeMinorVersion: true + settings: { + configuration: { + url: dscAgentPackageLocation + script: 'Configuration.ps1' + function: 'DomainJoinFileShare' + } + configurationArguments: { + storageAccountName: storageAccountName + storageAccountRG: storageAccountRG + DomainName: domainName + AzureCloudEnvironment: AzureCloudEnvironment + DomainAdminUserName: domainAdminUsername + } + } + protectedSettings: { + configurationArguments: { + DomainAdminUserPassword: domainAdminPassword + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/configure-fslogix-session-hosts.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/configure-fslogix-session-hosts.bicep new file mode 100644 index 000000000..d62de4404 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/configure-fslogix-session-hosts.bicep @@ -0,0 +1,21 @@ +param name string +param location string +param baseScriptUri string +param file string +param FsLogixScriptArguments string + +resource fslogixconfigure 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/configurefslogix' + location: location + properties: { + publisher: 'Microsoft.Compute' + type: 'CustomScriptExtension' + typeHandlerVersion: '1.10' + autoUpgradeMinorVersion: true + settings: {} + protectedSettings: { + fileUris: array(baseScriptUri) + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File ${file} ${FsLogixScriptArguments}' + } + } +} diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/deploy.bicep b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/deploy.bicep new file mode 100644 index 000000000..f7a048e1a --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/deploy.bicep @@ -0,0 +1,74 @@ +@description('Required. The name of the virtual machine that extension is provisioned for') +param virtualMachineName string + +@description('Required. The name of the virtual machine extension') +param name string + +@description('Optional. The location the extension is deployed to') +param location string = resourceGroup().location + +@description('Required. The name of the extension handler publisher') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension"') +param type string + +@description('Required. Specifies the version of the script handler') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available') +param enableAutomaticUpgrade bool + +@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 virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: virtualMachineName +} + +resource extension 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: name + parent: virtualMachine + location: location + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The resource ID of the extension') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/readme.md b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/readme.md new file mode 100644 index 000000000..fd094e6b4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/readme.md @@ -0,0 +1,39 @@ +# Virtual Machine Extensions `[Microsoft.Compute/virtualMachines/extensions]` + +This module deploys a virtual machine extension. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachines/extensions` | 2021-07-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `autoUpgradeMinorVersion` | bool | | | Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enableAutomaticUpgrade` | bool | | | Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available | +| `forceUpdateTag` | string | | | Optional. How the extension handler should be forced to update even if the extension configuration has not changed | +| `location` | string | `[resourceGroup().location]` | | Optional. The location the extension is deployed to | +| `name` | string | | | Required. The name of the virtual machine extension | +| `protectedSettings` | secureObject | `{object}` | | Optional. Any object that contains the extension specific protected settings | +| `publisher` | string | | | Required. The name of the extension handler publisher | +| `settings` | object | `{object}` | | Optional. Any object that contains the extension specific settings | +| `supressFailures` | bool | | | Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false | +| `type` | string | | | Required. Specifies the type of the extension; an example is "CustomScriptExtension" | +| `typeHandlerVersion` | string | | | Required. Specifies the version of the script handler | +| `virtualMachineName` | string | | | Required. The name of the virtual machine that extension is provisioned for | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The resource ID of the extension | + +## Template references + +- [Virtualmachines/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/version.json b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/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/carml/1.0.0/Microsoft.Compute/virtualMachines/readme.md b/carml/1.0.0/Microsoft.Compute/virtualMachines/readme.md new file mode 100644 index 000000000..e7d050387 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/readme.md @@ -0,0 +1,550 @@ +# Virtual Machines `[Microsoft.Compute/virtualMachines]` + +This module deploys one Virtual Machine with one or multiple nics and optionally one or multiple public IPs. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Automanage/configurationProfileAssignments` | 2021-04-30-preview | +| `Microsoft.Compute/virtualMachines` | 2021-07-01 | +| `Microsoft.Compute/virtualMachines/extensions` | 2021-07-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/networkInterfaces` | 2021-03-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | | | Optional. When specifying a Windows Virtual Machine, this value should be passed | +| `adminUsername` | secureString | | | Required. Administrator username | +| `allowExtensionOperations` | bool | `True` | | Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine. | +| `availabilitySetName` | string | | | Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set. | +| `availabilityZone` | int | `0` | `[0, 1, 2, 3]` | Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set. | +| `backupPolicyName` | string | `DefaultPolicy` | | Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. | +| `backupVaultName` | string | | | Optional. Recovery service vault name to add VMs to backup. | +| `backupVaultResourceGroup` | string | `[resourceGroup().name]` | | Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a registration token. | +| `bootDiagnosticStorageAccountName` | string | | | Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Optional. Storage account boot diagnostic base URI. | +| `certificatesToBeInstalled` | array | `[]` | | Optional. Specifies set of certificates that should be installed onto the virtual machine. | +| `configurationProfileAssignments` | array | `[]` | | Optional. Any VM configuration profile assignments | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customData` | string | | | Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `dedicatedHostId` | string | | | Optional. Specifies resource ID about the dedicated host that the virtual machine resides in. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `disablePasswordAuthentication` | bool | `False` | | Optional. Specifies whether password authentication should be disabled. | +| `enableAutomaticUpdates` | bool | `True` | | Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableEvictionPolicy` | bool | `False` | | Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | `False` | | Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `extensionAntiMalwareConfig` | object | `{object}` | | Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDependencyAgentConfig` | object | `{object}` | | Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | | | Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `imageReference` | object | | | Required. OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `licenseType` | string | | `[Windows_Client, Windows_Server, ]` | Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `maxPriceForLowPriorityVm` | string | | | Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `monitoringWorkspaceId` | string | | | Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true. | +| `name` | string | `[take(toLower(uniqueString(resourceGroup().name)), 10)]` | | Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name. | +| `nicConfigurations` | array | | | Required. Configures NICs and PIPs. | +| `nicMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `osDisk` | object | | | Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `osType` | string | | `[Windows, Linux]` | Required. The chosen OS type | +| `pipLogsToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | Optional. The name of logs that will be streamed. | +| `pipMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `plan` | object | `{object}` | | Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | | | Optional. Resource name of a proximity placement group. | +| `publicKeys` | array | `[]` | | Optional. The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sasTokenValidityLength` | string | `PT8H` | | Optional. SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `secureBootEnabled` | bool | `False` | | Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `securityType` | string | | | Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. | +| `systemAssignedIdentity` | bool | `False` | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `timeZone` | string | | | Optional. Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | `False` | | Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `vmComputerNamesTransformation` | string | `none` | | Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'. | +| `vmPriority` | string | `Regular` | `[Regular, Low, Spot]` | Optional. Specifies the priority for the virtual machine. | +| `vmSize` | string | `Standard_D2s_v3` | | Optional. Specifies the size for the VMs | +| `vTpmEnabled` | bool | `False` | | Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | + +### Parameter Usage: `imageReference` + +#### Marketplace images + +```json +"imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } +} +``` + +#### Custom images + +```json +"imageReference": { + "value": { + "id": "/subscriptions/12345-6789-1011-1213-15161718/resourceGroups/rg-name/providers/Microsoft.Compute/images/imagename" + } +} +``` + +### Parameter Usage: `plan` + +```json +"plan": { + "value": { + "name": "qvsa-25", + "product": "qualys-virtual-scanner", + "publisher": "qualysguard" + } +} +``` + +### Parameter Usage: `osDisk` + +```json + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { // Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. + "id": "/subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/" + } + } + } +} +``` + +### Parameter Usage: `dataDisks` + +```json +"dataDisks": { + "value": [{ + "caching": "ReadOnly", + "createOption": "Empty", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }] +} +``` + +### Parameter Usage: `windowsConfiguration` + +To set the time zone of a VM with the timeZone parameter inside windowsConfiguration, use the following PS command to get the correct options: + +```powershell +Get-TimeZone -ListAvailable | Select ID +``` + +```json +"windowsConfiguration": { + "provisionVMAgent": "boolean", + "enableAutomaticUpdates": "boolean", + "timeZone": "string", + "additionalUnattendContent": [ + { + "passName": "OobeSystem", + "componentName": "Microsoft-Windows-Shell-Setup", + "settingName": "string", + "content": "string" + } + ], + "winRM": { + "listeners": [ + { + "protocol": "string", + "certificateUrl": "string" + } + ] + } +} +``` + +### Parameter Usage: `linuxConfiguration` + +```json +"linuxConfiguration": { + "disablePasswordAuthentication": "boolean", + "ssh": { + "publicKeys": [ + { + "path": "string", + "keyData": "string" + } + ] + }, + "provisionVMAgent": "boolean" + }, + "secrets": [ + { + "sourceVault": { + "id": "string" + }, + "vaultCertificates": [ + { + "certificateUrl": "string", + "certificateStore": "string" + } + ] + } + ], + "allowExtensionOperations": "boolean", + "requireGuestProvisionSignal": "boolean" +} +``` + +### Parameter Usage: `nicConfigurations` + +Comments: +- The field `nicSuffix` and `subnetId` are mandatory. +- If `enablePublicIP` is set to true, then `publicIpNameSuffix` is also mandatory. +- Each IP config needs to have the mandatory field `name`. +- If not disabled, `enableAcceleratedNetworking` is considered `true` by default and requires the VM to be deployed with a supported OS and VM size. + +```json +"nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "ipConfigurations": [ + { + "name": "ipconfig1", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "" + ] + } + ] + } + }, + { + "name": "ipconfig2", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + } + ], + "nsgId": "/subscriptions//resourceGroups//providers/Microsoft.Network/networkSecurityGroups/", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "" + ] + } + ] + }, + { + "nicSuffix": "-nic-02", + "ipConfigurations": [ + { + "name": "ipconfig1", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-02" + } + }, + { + "name": "ipconfig2", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "privateIPAllocationMethod": "Static", + "vmIPAddress": "10.0.0.9" + } + ] + } + ] +} +``` + +### Parameter Usage: `configurationProfileAssignments` + +```json +"configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest" + ] +} +``` + +### Parameter Usage: `domainJoinSettings` + +```json +"enableDomainJoinExtension": { + "value": true +}, +"domainJoinSettings": { + "value": { + "domainName": "contoso.com", + "domainJoinUser": "test.user@testcompany.com", + "domainJoinOU": "OU=testOU; DC=contoso; DC=com", + "domainJoinRestart": true, + "domainJoinOptions": 3 + } +}, +"domainJoinPassword": { + "keyVault": { + "id": "/subscriptions/62826c76-d304-46d8-a0f6-718dbdcc536c/resourceGroups/WVD-Mgmt-TO-RG/providers/Microsoft.KeyVault/vaults/wvd-to-kvlt" + }, + "secretName": "domainJoinUser02-Password" +} +``` + +### Parameter Usage: `microsoftAntiMalwareSettings` + +Only for OSType Windows + +```json +"enableMicrosoftAntiMalware": { + "value": true +}, +"microsoftAntiMalwareSettings": { + "value": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } +} +``` + +### Parameter Usage: `diskEncryptionSettings` + +```json +"enableWindowsDiskEncryption": { + "value": true +}, +"diskEncryptionSettings": { + "value": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://mykeyvault.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionKeyURL": "https://mykeyvault.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", //'RSA-OAEP'/'RSA-OAEP-256'/'RSA1_5' + "VolumeType": "All", //'OS'/'Data'/'All' + "ResizeOSDisk": "false" + } +} +``` + +### Parameter Usage: `desiredStateConfigurationSettings` + +```json +"enableDesiredStateConfiguration": { + "value": true +}, +"desiredStateConfigurationSettings": { + "value": { + { + "wmfVersion": "latest", + "configuration": { + "url": "http://validURLToConfigLocation", + "script": "ConfigurationScript.ps1", + "function": "ConfigurationFunction" + }, + "configurationArguments": { + "argument1": "Value1", + "argument2": "Value2" + }, + "configurationData": { + "url": "https://foo.psd1" + }, + "privacy": { + "dataCollection": "enable" + }, + "advancedOptions": { + "forcePullAndApply": false, + "downloadMappings": { + "specificDependencyKey": "https://myCustomDependencyLocation" + } + } + } + } +}, +"desiredStateConfigurationProtectedSettings":{ + "value":{ + "configurationArguments": { + "mySecret": "MyPlaceholder" + }, + "configurationUrlSasToken": "MyPlaceholder", + "configurationDataUrlSasToken": "MyPlaceholder" + } +} +``` + +### Parameter Usage: `windowsScriptExtensionFileData` + +```json +"enableCustomScriptExtension": { + "value": true +}, +"windowsScriptExtensionFileData": { + "value": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + //storage account with public container (no SAS token is required) OR other public URL (not a storage account) + { + "uri": "https://github.com/myProject/File3.ps1", + "storageAccountId": "" + } + ] +} +``` + +### Parameter Usage: `windowsScriptExtensionFileData` with native storage account key support + +```json +"enableCustomScriptExtension": { + "value": true +}, +"windowsScriptExtensionFileData": { + "value": [ + { + "https://mystorageaccount.blob.core.windows.net/avdscripts/testscript.ps1" + } + ] +}, +"windowsScriptExtensionCommandToExecute": { + "value": "powershell -ExecutionPolicy Unrestricted -File testscript.ps1" +}, +"cseStorageAccountName": { + "value": "mystorageaccount" +}, +"cseStorageAccountKey": { + "value": "MyPlaceholder" +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VM. | +| `resourceGroupName` | string | The name of the resource group the VM was created in. | +| `resourceId` | string | The resource ID of the VM. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Define resources with Bicep and ARM templates](https://docs.microsoft.com/en-us/azure/templates) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networkinterfaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/networkInterfaces) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Backupfabrics/Protectioncontainers/Protecteditems](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-06-01/vaults/backupFabrics/protectionContainers/protectedItems) +- [Virtualmachines](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines) +- [Virtualmachines/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) diff --git a/carml/1.0.0/Microsoft.Compute/virtualMachines/version.json b/carml/1.0.0/Microsoft.Compute/virtualMachines/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Compute/virtualMachines/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/carml/1.0.0/Microsoft.Consumption/budgets/.parameters/parameters.json b/carml/1.0.0/Microsoft.Consumption/budgets/.parameters/parameters.json new file mode 100644 index 000000000..4ab50cd80 --- /dev/null +++ b/carml/1.0.0/Microsoft.Consumption/budgets/.parameters/parameters.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "amount": { + "value": 500 + }, + "thresholds": { + "value": [ + 50, + 75, + 90, + 100, + 110 + ] + }, + "contactEmails": { + "value": [ + "dummy@contoso.com" + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Consumption/budgets/deploy.bicep b/carml/1.0.0/Microsoft.Consumption/budgets/deploy.bicep new file mode 100644 index 000000000..e1784f25c --- /dev/null +++ b/carml/1.0.0/Microsoft.Consumption/budgets/deploy.bicep @@ -0,0 +1,89 @@ +targetScope = 'subscription' + +@description('Optional. The name of the budget.') +param name string = '' + +@allowed([ + 'Cost' + 'Usage' +]) +@description('Optional. The category of the budget, whether the budget tracks cost or usage.') +param category string = 'Cost' + +@description('Required. The total amount of cost or usage to track with the budget.') +param amount int + +@allowed([ + 'Monthly' + 'Quarterly' + 'Annually' + 'BillingMonth' + 'BillingQuarter' + 'BillingAnnual' +]) +@description('Optional. The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers.') +param resetPeriod string = 'Monthly' + +@description('Required. The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month).') +param startDate string = '${utcNow('yyyy')}-${utcNow('MM')}-01T00:00:00Z' + +@description('Optional. The end date for the budget. If not provided, it will default to 10 years from the start date.') +param endDate string = '' + +@maxLength(5) +@description('Optional. Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000.') +param thresholds array = [ + 50 + 75 + 90 + 100 + 110 +] + +@description('Optional. The list of email addresses to send the budget notification to when the thresholds are exceeded.') +param contactEmails array = [] + +@description('Optional. The list of contact roles to send the budget notification to when the thresholds are exceeded.') +param contactRoles array = [] + +@description('Optional. List of action group resource IDs that will receive the alert.') +param actionGroups array = [] + +var budgetNameVar = empty(name) ? '${resetPeriod}-${category}-Budget' : name +var notificationsArray = [for threshold in thresholds: { + 'Actual_GreaterThan_${threshold}_Percentage': { + enabled: true + operator: 'GreaterThan' + threshold: threshold + contactEmails: empty(contactEmails) ? null : array(contactEmails) + contactRoles: empty(contactRoles) ? null : array(contactRoles) + contactGroups: empty(actionGroups) ? null : array(actionGroups) + thresholdType: 'Actual' + } +}] + +var notifications = json(replace(replace(replace(string(notificationsArray), '[{', '{'), '}]', '}'), '}},{', '},')) + +resource budget 'Microsoft.Consumption/budgets@2019-05-01' = { + name: budgetNameVar + properties: { + category: category + amount: amount + timeGrain: resetPeriod + timePeriod: { + startDate: startDate + endDate: endDate + } + filter: {} + notifications: notifications + } +} + +@description('The name of the budget') +output name string = budget.name + +@description('The resource ID of the budget') +output resourceId string = budget.id + +@description('The subscription the budget was deployed into') +output subscriptionName string = subscription().displayName diff --git a/carml/1.0.0/Microsoft.Consumption/budgets/readme.md b/carml/1.0.0/Microsoft.Consumption/budgets/readme.md new file mode 100644 index 000000000..47cfa0b88 --- /dev/null +++ b/carml/1.0.0/Microsoft.Consumption/budgets/readme.md @@ -0,0 +1,36 @@ +# Budgets `[Microsoft.Consumption/budgets]` + +This module deploys budgets for subscriptions. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Consumption/budgets` | 2019-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actionGroups` | array | `[]` | | Optional. List of action group resource IDs that will receive the alert. | +| `amount` | int | | | Required. The total amount of cost or usage to track with the budget. | +| `category` | string | `Cost` | `[Cost, Usage]` | Optional. The category of the budget, whether the budget tracks cost or usage. | +| `contactEmails` | array | `[]` | | Optional. The list of email addresses to send the budget notification to when the thresholds are exceeded. | +| `contactRoles` | array | `[]` | | Optional. The list of contact roles to send the budget notification to when the thresholds are exceeded. | +| `endDate` | string | | | Optional. The end date for the budget. If not provided, it will default to 10 years from the start date. | +| `name` | string | | | Optional. The name of the budget. | +| `resetPeriod` | string | `Monthly` | `[Monthly, Quarterly, Annually, BillingMonth, BillingQuarter, BillingAnnual]` | Optional. The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers. | +| `startDate` | string | `[format('{0}-{1}-01T00:00:00Z', utcNow('yyyy'), utcNow('MM'))]` | | Required. The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month). | +| `thresholds` | array | `[50, 75, 90, 100, 110]` | | Optional. Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the budget | +| `resourceId` | string | The resource ID of the budget | +| `subscriptionName` | string | The subscription the budget was deployed into | + +## Template references + +- [Budgets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Consumption/2019-05-01/budgets) diff --git a/carml/1.0.0/Microsoft.Consumption/budgets/version.json b/carml/1.0.0/Microsoft.Consumption/budgets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Consumption/budgets/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/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/.parameters/parameters.json new file mode 100644 index 000000000..1fdcb27db --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/.parameters/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": "<>-az-acg-x-001" + }, + "containerName": { + "value": "<>-az-aci-x-001" + }, + "image": { + "value": "mcr.microsoft.com/azuredocs/aci-helloworld" + }, + "ports": { + "value": [ + { + "protocol": "Tcp", + "port": "80" + }, + { + "protocol": "Tcp", + "port": "443" + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/deploy.bicep b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/deploy.bicep new file mode 100644 index 000000000..e91376ab5 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/deploy.bicep @@ -0,0 +1,129 @@ +@description('Required. Name for the container group.') +param name string + +@description('Required. Name for the container.') +param containername string + +@description('Required. Name of the image.') +param image string + +@description('Optional. Port to open on the container and the public IP address.') +param ports array = [ + { + name: 'Tcp' + value: '443' + } +] + +@description('Optional. The number of CPU cores to allocate to the container.') +param cpuCores int = 2 + +@description('Optional. The amount of memory to allocate to the container in gigabytes.') +param memoryInGB int = 2 + +@description('Optional. The operating system type required by the containers in the container group. - Windows or Linux.') +param osType string = 'Linux' + +@description('Optional. Restart policy for all containers within the container group. - Always: Always restart. OnFailure: Restart on failure. Never: Never restart. - Always, OnFailure, Never') +param restartPolicy string = 'Always' + +@description('Optional. Specifies if the IP is exposed to the public internet or private VNET. - Public or Private') +param ipAddressType string = 'Public' + +@description('Optional. The image registry credentials by which the container group is created from.') +param imageRegistryCredentials array = [] + +@description('Optional. Envrionment variables of the container group.') +param environmentVariables array = [] + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource containergroup 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = { + name: name + location: location + identity: identity + tags: tags + properties: { + containers: [ + { + name: containername + properties: { + command: [] + image: image + ports: ports + resources: { + requests: { + cpu: cpuCores + memoryInGB: memoryInGB + } + } + environmentVariables: environmentVariables + } + } + ] + imageRegistryCredentials: imageRegistryCredentials + restartPolicy: restartPolicy + osType: osType + ipAddress: { + type: ipAddressType + ports: ports + } + } +} + +resource containergroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${containergroup.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: containergroup +} + +@description('The name of the container group') +output name string = containergroup.name + +@description('The resource ID of the container group') +output resourceId string = containergroup.id + +@description('The resource group the container group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The IPv4 address of the container group') +output iPv4Address string = containergroup.properties.ipAddress.ip + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(containergroup.identity, 'principalId') ? containergroup.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/readme.md b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/readme.md new file mode 100644 index 000000000..14e40fda5 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/readme.md @@ -0,0 +1,94 @@ +# Container Instances `[Microsoft.ContainerInstance/containerGroups]` + +### Container groups in Azure Container Instances + +The top-level resource in Azure Container Instances is the container group. A container group is a collection of containers that get scheduled on the same host machine. The containers in a container group share a lifecycle, resources, local network, and storage volumes. It's similar in concept to a pod in Kubernetes. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.ContainerInstance/containerGroups` | 2021-03-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `containername` | string | | | Required. Name for the container. | +| `cpuCores` | int | `2` | | Optional. The number of CPU cores to allocate to the container. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `environmentVariables` | array | `[]` | | Optional. Envrionment variables of the container group. | +| `image` | string | | | Required. Name of the image. | +| `imageRegistryCredentials` | array | `[]` | | Optional. The image registry credentials by which the container group is created from. | +| `ipAddressType` | string | `Public` | | Optional. Specifies if the IP is exposed to the public internet or private VNET. - Public or Private | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `memoryInGB` | int | `2` | | Optional. The amount of memory to allocate to the container in gigabytes. | +| `name` | string | | | Required. Name for the container group. | +| `osType` | string | `Linux` | | Optional. The operating system type required by the containers in the container group. - Windows or Linux. | +| `ports` | array | `[System.Collections.Hashtable]` | | Optional. Port to open on the container and the public IP address. | +| `restartPolicy` | string | `Always` | | Optional. Restart policy for all containers within the container group. - Always: Always restart. OnFailure: Restart on failure. Never: Never restart. - Always, OnFailure, Never | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `imageRegistryCredentials` + +The image registry credentials by which the container group is created from. + +```json + "imageRegistryCredentials": { + "value": [ + { + "server": "sxxazacrx001.azurecr.io", + "username": "sxxazacrx001" + } + ] + } +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `iPv4Address` | string | The IPv4 address of the container group | +| `name` | string | The name of the container group | +| `resourceGroupName` | string | The resource group the container group was deployed into | +| `resourceId` | string | The resource ID of the container group | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Containergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerInstance/2021-03-01/containerGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/version.json b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerInstance/containerGroups/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/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_privateEndpoints.bicep b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_privateEndpoints.bicep new file mode 100644 index 000000000..9deaf8c02 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_privateEndpoints.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? privateEndpointObj.privateDnsZoneResourceIds : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateEndpoint_privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d350e3174 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.bicep/nested_rbac.bicep @@ -0,0 +1,41 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'AcrDelete': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11') + 'AcrImageSigner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'AcrPush': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec') + 'AcrQuarantineReader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04') + 'AcrQuarantineWriter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource registry 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(registry.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: registry +}] diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.parameters/min.parameters.json new file mode 100644 index 000000000..255a9ddfc --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azacrmin001" + } + } +} diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/.parameters/parameters.json b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.parameters/parameters.json new file mode 100644 index 000000000..0b7604f9d --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/.parameters/parameters.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azacrx001" + }, + "acrAdminUserEnabled": { + "value": false + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/deploy.bicep b/carml/1.0.0/Microsoft.ContainerRegistry/registries/deploy.bicep new file mode 100644 index 000000000..7de9a5cac --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/deploy.bicep @@ -0,0 +1,216 @@ +@description('Required. Name of your Azure container registry') +@minLength(5) +@maxLength(50) +param name string + +@description('Optional. Enable admin user that have push / pull permission to the registry.') +param acrAdminUserEnabled bool = false + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tier of your Azure container registry.') +@allowed([ + 'Basic' + 'Standard' + 'Premium' +]) +param acrSku string = 'Basic' + +@description('Optional. The value that indicates whether the policy is enabled or not.') +param quarantinePolicyStatus string = '' + +@description('Optional. The value that indicates whether the policy is enabled or not.') +param trustPolicyStatus string = '' + +@description('Optional. The value that indicates whether the policy is enabled or not.') +param retentionPolicyStatus string = '' + +@description('Optional. The number of days to retain an untagged manifest after which it gets purged.') +param retentionPolicyDays string = '' + +@description('Optional. Enable a single data endpoint per region for serving data. Not relevant in case of disabled public access.') +param dataEndpointEnabled bool = false + +@description('Optional. Whether or not public network access is allowed for the container registry. - Enabled or Disabled') +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Whether to allow trusted Azure services to access a network restricted registry. Not relevant in case of public access. - AzureServices or None') +param networkRuleBypassOptions string = 'AzureServices' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ContainerRegistryRepositoryEvents' + 'ContainerRegistryLoginEvents' +]) +param logsToEnable array = [ + 'ContainerRegistryRepositoryEvents' + 'ContainerRegistryLoginEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource registry 'Microsoft.ContainerRegistry/registries@2021-09-01' = { + name: name + location: location + identity: identity + tags: tags + sku: { + name: acrSku + } + properties: { + adminUserEnabled: acrAdminUserEnabled + policies: { + quarantinePolicy: { + status: (empty(quarantinePolicyStatus) ? null : quarantinePolicyStatus) + } + trustPolicy: { + type: 'Notary' + status: (empty(trustPolicyStatus) ? null : trustPolicyStatus) + } + retentionPolicy: { + days: (empty(retentionPolicyDays) ? null : int(retentionPolicyDays)) + status: (empty(retentionPolicyStatus) ? null : retentionPolicyStatus) + } + } + dataEndpointEnabled: dataEndpointEnabled + publicNetworkAccess: publicNetworkAccess + networkRuleBypassOptions: networkRuleBypassOptions + } +} + +resource registry_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${registry.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: registry +} + +resource registry_diagnosticSettingName 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${registry.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: registry +} + +module registry_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ContainerRegistry-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: registry.id + } +}] + +module registry_privateEndpoints '.bicep/nested_privateEndpoints.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-ContainerRegistry-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: registry.id + privateEndpointVnetLocation: empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The Name of the Azure container registry.') +output name string = registry.name + +@description('The reference to the Azure container registry.') +output loginServer string = reference(registry.id, '2019-05-01').loginServer + +@description('The name of the Azure container registry.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Azure container registry.') +output resourceId string = registry.id + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(registry.identity, 'principalId') ? registry.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/readme.md b/carml/1.0.0/Microsoft.ContainerRegistry/registries/readme.md new file mode 100644 index 000000000..65d628a2c --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/readme.md @@ -0,0 +1,166 @@ +# Container Registries `[Microsoft.ContainerRegistry/registries]` + +Azure Container Registry is a managed, private Docker registry service based on the open-source Docker Registry 2.0. Create and maintain Azure container registries to store and manage your private Docker container images and related artifacts. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ContainerRegistry/registries` | 2021-09-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-02-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `acrAdminUserEnabled` | bool | | | Optional. Enable admin user that have push / pull permission to the registry. | +| `acrSku` | string | `Basic` | `[Basic, Standard, Premium]` | Optional. Tier of your Azure container registry. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `dataEndpointEnabled` | bool | | | Optional. Enable a single data endpoint per region for serving data. Not relevant in case of disabled public access. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ContainerRegistryRepositoryEvents, ContainerRegistryLoginEvents]` | `[ContainerRegistryRepositoryEvents, ContainerRegistryLoginEvents]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of your Azure container registry | +| `networkRuleBypassOptions` | string | `AzureServices` | | Optional. Whether to allow trusted Azure services to access a network restricted registry. Not relevant in case of public access. - AzureServices or None | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `publicNetworkAccess` | string | `Enabled` | | Optional. Whether or not public network access is allowed for the container registry. - Enabled or Disabled | +| `quarantinePolicyStatus` | string | | | Optional. The value that indicates whether the policy is enabled or not. | +| `retentionPolicyDays` | string | | | Optional. The number of days to retain an untagged manifest after which it gets purged. | +| `retentionPolicyStatus` | string | | | Optional. The value that indicates whether the policy is enabled or not. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `trustPolicyStatus` | string | | | Optional. The value that indicates whether the policy is enabled or not. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `imageRegistryCredentials` + +The image registry credentials by which the container group is created from. + +```json + "acrName": { + "value": { + "server": "acrx001", + } + }, + "acrAdminUserEnabled": { + "value": false + } +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `loginServer` | string | The reference to the Azure container registry. | +| `name` | string | The Name of the Azure container registry. | +| `resourceGroupName` | string | The name of the Azure container registry. | +| `resourceId` | string | The resource ID of the Azure container registry. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Registries](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerRegistry/2021-09-01/registries) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.ContainerRegistry/registries/version.json b/carml/1.0.0/Microsoft.ContainerRegistry/registries/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerRegistry/registries/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/carml/1.0.0/Microsoft.ContainerService/managedClusters/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..7cb5a582b --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.bicep/nested_rbac.bicep @@ -0,0 +1,41 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8') + 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f') + 'Azure Kubernetes Service Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8') + 'Azure Kubernetes Service RBAC Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3498e952-d568-435e-9b2c-8d77e338d7f7') + 'Azure Kubernetes Service RBAC Cluster Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b') + 'Azure Kubernetes Service RBAC Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f6c6a51-bcf8-42ba-9220-52d62157d7db') + 'Azure Kubernetes Service RBAC Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2021-07-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(managedCluster.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: managedCluster +}] diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/.parameters/azure.parameters.json b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.parameters/azure.parameters.json new file mode 100644 index 000000000..10a7e7af1 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.parameters/azure.parameters.json @@ -0,0 +1,117 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-aks-azure-001" + }, + "primaryAgentPoolProfile": { + "value": [ + { + "name": "systempool", + "osDiskSizeGB": 0, + "count": 1, + "enableAutoScaling": true, + "minCount": 1, + "maxCount": 3, + "vmSize": "Standard_DS2_v2", + "osType": "Linux", + "storageProfile": "ManagedDisks", + "type": "VirtualMachineScaleSets", + "mode": "System", + "vnetSubnetID": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-aks/subnets/Primary", + "serviceCidr": "", + "maxPods": 30, + "availabilityZones": [ + "1" + ] + } + ] + }, + "aksClusterNetworkPlugin": { + "value": "azure" + }, + "agentPools": { + "value": [ + { + "name": "userpool1", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User", + "vnetSubnetID": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-aks/subnets/Secondary" + }, + { + "name": "userpool2", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User", + "vnetSubnetID": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-aks/subnets/Tertiary" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/.parameters/kubenet.parameters.json b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.parameters/kubenet.parameters.json new file mode 100644 index 000000000..3e274f46c --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/.parameters/kubenet.parameters.json @@ -0,0 +1,116 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-aks-kubenet-001" + }, + "primaryAgentPoolProfile": { + "value": [ + { + "name": "systempool", + "osDiskSizeGB": 0, + "count": 1, + "enableAutoScaling": true, + "minCount": 1, + "maxCount": 3, + "vmSize": "Standard_DS2_v2", + "osType": "Linux", + "storageProfile": "ManagedDisks", + "type": "VirtualMachineScaleSets", + "mode": "System", + "serviceCidr": "", + "maxPods": 30, + "availabilityZones": [ + "1" + ] + } + ] + }, + "aksClusterNetworkPlugin": { + "value": "kubenet" + }, + "agentPools": { + "value": [ + { + "name": "userpool1", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User" + }, + { + "name": "userpool2", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/deploy.bicep b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/deploy.bicep new file mode 100644 index 000000000..e5c76a6d5 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/deploy.bicep @@ -0,0 +1,235 @@ +@description('Required. Name of the managed cluster') +@minLength(1) +param managedClusterName string + +@description('Required. Name of the agent pool') +param name string + +@description('Optional. The list of Availability zones to use for nodes. This can only be specified if the AgentPoolType property is "VirtualMachineScaleSets". ') +param availabilityZones array = [] + +@description('Optional. Desired Number of agents (VMs) specified to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1.') +@minValue(0) +@maxValue(1000) +param count int = 1 + +@description('Optional. This is the ARM ID of the source object to be used to create the target object.') +param sourceResourceId string = '' + +@description('Optional. Whether to enable auto-scaler') +@allowed([ + true + false +]) +param enableAutoScaling bool = false + +@description('Optional. This is only supported on certain VM sizes and in certain Azure regions. For more information, see: /azure/aks/enable-host-encryption ') +@allowed([ + true + false +]) +param enableEncryptionAtHost bool = false + +@description('Optional. See Add a FIPS-enabled node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool-preview) for more details.') +@allowed([ + true + false +]) +param enableFIPS bool = false + +@description('Optional. Some scenarios may require nodes in a node pool to receive their own dedicated public IP addresses. A common scenario is for gaming workloads, where a console needs to make a direct connection to a cloud virtual machine to minimize hops. For more information see assigning a public IP per node (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools). The default is false.') +@allowed([ + true + false +]) +param enableNodePublicIP bool = false + +@description('Optional. Whether to enable UltraSSD') +@allowed([ + true + false +]) +param enableUltraSSD bool = false + +@description('Optional. GPUInstanceProfile to be used to specify GPU MIG instance profile for supported GPU VM SKU.') +@allowed([ + 'MIG1g' + 'MIG2g' + 'MIG3g' + 'MIG4g' + 'MIG7g' + '' +]) +param gpuInstanceProfile string = '' + +@description('Optional. Determines the placement of emptyDir volumes, container runtime data root, and Kubelet ephemeral storage.') +param kubeletDiskType string = '' + +@description('Optional. The maximum number of nodes for auto-scaling') +param maxCount int = -1 + +@description('Optional. The maximum number of pods that can run on a node.') +param maxPods int = -1 + +@description('Optional. The minimum number of nodes for auto-scaling') +param minCount int = -1 + +@description('Optional. A cluster must have at least one "System" Agent Pool at all times. For additional information on agent pool restrictions and best practices, see: /azure/aks/use-system-pools') +param mode string = '' + +@description('Optional. The node labels to be persisted across all nodes in agent pool.') +param nodeLabels object = {} + +@description('Optional. ResourceId of the node PublicIPPrefix') +param nodePublicIpPrefixId string = '' + +@description('Optional. The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. ') +param nodeTaints array = [] + +@description('Optional. As a best practice, you should upgrade all node pools in an AKS cluster to the same Kubernetes version. The node pool version must have the same major version as the control plane. The node pool minor version must be within two minor versions of the control plane version. The node pool version cannot be greater than the control plane version. For more information see upgrading a node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#upgrade-a-node-pool).') +param orchestratorVersion string = '' + +@description('Optional. OS Disk Size in GB to be used to specify the disk size for every machine in the master/agent pool. If you specify 0, it will apply the default osDisk size according to the vmSize specified.') +param osDiskSizeGB int = 0 + +@description('Optional. The default is "Ephemeral" if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, defaults to "Managed". May not be changed after creation. For more information see Ephemeral OS (https://docs.microsoft.com/en-us/azure/aks/cluster-configuration#ephemeral-os).') +@allowed([ + 'Ephemeral' + 'Managed' + '' +]) +param osDiskType string = '' + +@description('Optional. Specifies an OS SKU. This value must not be specified if OSType is Windows.') +@allowed([ + 'CBLMariner' + 'Ubuntu' + '' +]) +param osSku string = '' + +@description('Optional. The operating system type. The default is Linux.') +@allowed([ + 'Linux' + 'Windows' +]) +param osType string = 'Linux' + +@description('Optional. Subnet ID for the pod IPs. If omitted, pod IPs are statically assigned on the node subnet (see vnetSubnetID for more details). This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} ') +param podSubnetId string = '' + +@description('Optional. The ID for the Proximity Placement Group.') +param proximityPlacementGroupId string = '' + +@description('Optional. Describes how VMs are added to or removed from Agent Pools. See billing states (https://docs.microsoft.com/en-us/azure/virtual-machines/states-billing).') +@allowed([ + 'Deallocate' + 'Delete' +]) +param scaleDownMode string = 'Delete' + +@description('Optional. The eviction policy specifies what to do with the VM when it is evicted. The default is Delete. For more information about eviction see spot VMs ') +@allowed([ + 'Deallocate' + 'Delete' +]) +param scaleSetEvictionPolicy string = 'Delete' + +@description('Optional. The Virtual Machine Scale Set priority.') +@allowed([ + 'Regular' + 'Spot' + '' +]) +param scaleSetPriority string = '' + +@description('Optional. Possible values are any decimal value greater than zero or -1 which indicates the willingness to pay any on-demand price. For more details on spot pricing, see spot VMs pricing (https://docs.microsoft.com/en-us/azure/virtual-machines/spot-vms#pricing)') +param spotMaxPrice int = -1 + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The type of Agent Pool.') +param type string = '' + +@description('Optional. This can either be set to an integer (e.g. "5") or a percentage (e.g. "50%"). If a percentage is specified, it is the percentage of the total agent pool size at the time of the upgrade. For percentages, fractional nodes are rounded up. If not specified, the default is 1. For more information, including best practices, see: /azure/aks/upgrade-cluster#customize-node-surge-upgrade') +param maxSurge string = '' + +@description('Optional. VM size. VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: /azure/aks/quotas-skus-regions') +param vmSize string = 'Standard_D2s_v3' + +@description('Optional. Node Subnet ID. If this is not specified, a VNET and subnet will be generated and used. If no podSubnetID is specified, this applies to nodes and pods, otherwise it applies to just nodes. This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} ') +param vnetSubnetId string = '' + +@description('Optional. Determines the type of workload a node can run.') +param workloadRuntime string = '' + +var creationData = { + sourceResourceId: !empty(sourceResourceId) ? sourceResourceId : null +} + +var upgradeSettings = { + maxSurge: maxSurge +} + +@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 managedCluster 'Microsoft.ContainerService/managedClusters@2021-08-01' existing = { + name: managedClusterName +} + +resource agentPool 'Microsoft.ContainerService/managedClusters/agentPools@2021-08-01' = { + name: name + parent: managedCluster + properties: { + availabilityZones: availabilityZones + count: count + creationData: !empty(sourceResourceId) ? creationData : null + enableAutoScaling: enableAutoScaling + enableEncryptionAtHost: enableEncryptionAtHost + enableFIPS: enableFIPS + enableNodePublicIP: enableNodePublicIP + enableUltraSSD: enableUltraSSD + gpuInstanceProfile: !empty(gpuInstanceProfile) ? gpuInstanceProfile : null + kubeletDiskType: kubeletDiskType + maxCount: maxCount != -1 ? maxCount : null + maxPods: maxPods != -1 ? maxPods : null + minCount: minCount != -1 ? minCount : null + mode: !empty(mode) ? mode : null + nodeLabels: nodeLabels + nodePublicIPPrefixID: !empty(nodePublicIpPrefixId) ? nodePublicIpPrefixId : null + nodeTaints: nodeTaints + orchestratorVersion: orchestratorVersion + osDiskSizeGB: osDiskSizeGB != -1 ? osDiskSizeGB : null + osDiskType: !empty(osDiskType) ? osDiskType : null + osSKU: !empty(osSku) ? osSku : null + osType: osType + podSubnetID: !empty(podSubnetId) ? podSubnetId : null + proximityPlacementGroupID: !empty(proximityPlacementGroupId) ? proximityPlacementGroupId : null + scaleDownMode: scaleDownMode + scaleSetEvictionPolicy: scaleSetEvictionPolicy + scaleSetPriority: !empty(scaleSetPriority) ? scaleSetPriority : null + spotMaxPrice: spotMaxPrice + tags: tags + type: type + upgradeSettings: upgradeSettings + vmSize: vmSize + vnetSubnetID: vnetSubnetId + workloadRuntime: workloadRuntime + } +} + +@description('The name of the agent pool') +output name string = agentPool.name + +@description('The resource ID of the agent pool') +output resourceId string = agentPool.id + +@description('The resource group the agent pool was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/readme.md b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/readme.md new file mode 100644 index 000000000..af872ec00 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/readme.md @@ -0,0 +1,80 @@ +# Managed Cluster AgentPool `[Microsoft.ContainerService/managedClusters/agentPools]` + +This module deploys an Agent Pool for a Container Service Managed Cluster + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ContainerService/managedClusters/agentPools` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `availabilityZones` | array | `[]` | | Optional. The list of Availability zones to use for nodes. This can only be specified if the AgentPoolType property is "VirtualMachineScaleSets". | +| `count` | int | `1` | | Optional. Desired Number of agents (VMs) specified to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enableAutoScaling` | bool | | `[True, False]` | Optional. Whether to enable auto-scaler | +| `enableEncryptionAtHost` | bool | | `[True, False]` | Optional. This is only supported on certain VM sizes and in certain Azure regions. For more information, see: /azure/aks/enable-host-encryption | +| `enableFIPS` | bool | | `[True, False]` | Optional. See Add a FIPS-enabled node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool-preview) for more details. | +| `enableNodePublicIP` | bool | | `[True, False]` | Optional. Some scenarios may require nodes in a node pool to receive their own dedicated public IP addresses. A common scenario is for gaming workloads, where a console needs to make a direct connection to a cloud virtual machine to minimize hops. For more information see assigning a public IP per node (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools). The default is false. | +| `enableUltraSSD` | bool | | `[True, False]` | Optional. Whether to enable UltraSSD | +| `gpuInstanceProfile` | string | | `[MIG1g, MIG2g, MIG3g, MIG4g, MIG7g, ]` | Optional. GPUInstanceProfile to be used to specify GPU MIG instance profile for supported GPU VM SKU. | +| `kubeletDiskType` | string | | | Optional. Determines the placement of emptyDir volumes, container runtime data root, and Kubelet ephemeral storage. | +| `managedClusterName` | string | | | Required. Name of the managed cluster | +| `maxCount` | int | `-1` | | Optional. The maximum number of nodes for auto-scaling | +| `maxPods` | int | `-1` | | Optional. The maximum number of pods that can run on a node. | +| `maxSurge` | string | | | Optional. This can either be set to an integer (e.g. "5") or a percentage (e.g. "50%"). If a percentage is specified, it is the percentage of the total agent pool size at the time of the upgrade. For percentages, fractional nodes are rounded up. If not specified, the default is 1. For more information, including best practices, see: /azure/aks/upgrade-cluster#customize-node-surge-upgrade | +| `minCount` | int | `-1` | | Optional. The minimum number of nodes for auto-scaling | +| `mode` | string | | | Optional. A cluster must have at least one "System" Agent Pool at all times. For additional information on agent pool restrictions and best practices, see: /azure/aks/use-system-pools | +| `name` | string | | | Required. Name of the agent pool | +| `nodeLabels` | object | `{object}` | | Optional. The node labels to be persisted across all nodes in agent pool. | +| `nodePublicIpPrefixId` | string | | | Optional. ResourceId of the node PublicIPPrefix | +| `nodeTaints` | array | `[]` | | Optional. The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. | +| `orchestratorVersion` | string | | | Optional. As a best practice, you should upgrade all node pools in an AKS cluster to the same Kubernetes version. The node pool version must have the same major version as the control plane. The node pool minor version must be within two minor versions of the control plane version. The node pool version cannot be greater than the control plane version. For more information see upgrading a node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#upgrade-a-node-pool). | +| `osDiskSizeGB` | int | | | Optional. OS Disk Size in GB to be used to specify the disk size for every machine in the master/agent pool. If you specify 0, it will apply the default osDisk size according to the vmSize specified. | +| `osDiskType` | string | | `[Ephemeral, Managed, ]` | Optional. The default is "Ephemeral" if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, defaults to "Managed". May not be changed after creation. For more information see Ephemeral OS (https://docs.microsoft.com/en-us/azure/aks/cluster-configuration#ephemeral-os). | +| `osSku` | string | | `[CBLMariner, Ubuntu, ]` | Optional. Specifies an OS SKU. This value must not be specified if OSType is Windows. | +| `osType` | string | `Linux` | `[Linux, Windows]` | Optional. The operating system type. The default is Linux. | +| `podSubnetId` | string | | | Optional. Subnet ID for the pod IPs. If omitted, pod IPs are statically assigned on the node subnet (see vnetSubnetID for more details). This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} | +| `proximityPlacementGroupId` | string | | | Optional. The ID for the Proximity Placement Group. | +| `scaleDownMode` | string | `Delete` | `[Deallocate, Delete]` | Optional. Describes how VMs are added to or removed from Agent Pools. See billing states (https://docs.microsoft.com/en-us/azure/virtual-machines/states-billing). | +| `scaleSetEvictionPolicy` | string | `Delete` | `[Deallocate, Delete]` | Optional. The eviction policy specifies what to do with the VM when it is evicted. The default is Delete. For more information about eviction see spot VMs | +| `scaleSetPriority` | string | | `[Regular, Spot, ]` | Optional. The Virtual Machine Scale Set priority. | +| `sourceResourceId` | string | | | Optional. This is the ARM ID of the source object to be used to create the target object. | +| `spotMaxPrice` | int | `-1` | | Optional. Possible values are any decimal value greater than zero or -1 which indicates the willingness to pay any on-demand price. For more details on spot pricing, see spot VMs pricing (https://docs.microsoft.com/en-us/azure/virtual-machines/spot-vms#pricing) | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `type` | string | | | Optional. The type of Agent Pool. | +| `vmSize` | string | `Standard_D2s_v3` | | Optional. VM size. VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: /azure/aks/quotas-skus-regions | +| `vnetSubnetId` | string | | | Optional. Node Subnet ID. If this is not specified, a VNET and subnet will be generated and used. If no podSubnetID is specified, this applies to nodes and pods, otherwise it applies to just nodes. This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} | +| `workloadRuntime` | string | | | Optional. Determines the type of workload a node can run. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the agent pool | +| `resourceGroupName` | string | The resource group the agent pool was deployed into. | +| `resourceId` | string | The resource ID of the agent pool | + +## Template references + +- [Managedclusters/Agentpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerService/2021-08-01/managedClusters/agentPools) diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/version.json b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/agentPools/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/carml/1.0.0/Microsoft.ContainerService/managedClusters/deploy.bicep b/carml/1.0.0/Microsoft.ContainerService/managedClusters/deploy.bicep new file mode 100644 index 000000000..08c5242fb --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/deploy.bicep @@ -0,0 +1,541 @@ +@description('Required. Specifies the name of the AKS cluster.') +param name string + +@description('Optional. Specifies the location of AKS cluster. It picks up Resource Group\'s location by default.') +param location string = resourceGroup().location + +@description('Optional. Specifies the DNS prefix specified when creating the managed cluster.') +param aksClusterDnsPrefix string = name + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Specifies the network plugin used for building Kubernetes network. - azure or kubenet.') +@allowed([ + '' + 'azure' + 'kubenet' +]) +param aksClusterNetworkPlugin string = '' + +@description('Optional. Specifies the network policy used for building Kubernetes network. - calico or azure') +@allowed([ + '' + 'azure' + 'calico' +]) +param aksClusterNetworkPolicy string = '' + +@description('Optional. Specifies the CIDR notation IP range from which to assign pod IPs when kubenet is used.') +param aksClusterPodCidr string = '' + +@description('Optional. A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges.') +param aksClusterServiceCidr string = '' + +@description('Optional. Specifies the IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr.') +param aksClusterDnsServiceIP string = '' + +@description('Optional. Specifies the CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range.') +param aksClusterDockerBridgeCidr string = '' + +@description('Optional. Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools.') +@allowed([ + 'basic' + 'standard' +]) +param aksClusterLoadBalancerSku string = 'standard' + +@description('Optional. Outbound IP Count for the Load balancer.') +param managedOutboundIPCount int = 0 + +@description('Optional. Specifies outbound (egress) routing method. - loadBalancer or userDefinedRouting.') +@allowed([ + 'loadBalancer' + 'userDefinedRouting' +]) +param aksClusterOutboundType string = 'loadBalancer' + +@description('Optional. Tier of a managed cluster SKU. - Free or Paid') +@allowed([ + 'Free' + 'Paid' +]) +param aksClusterSkuTier string = 'Free' + +@description('Optional. Version of Kubernetes specified when creating the managed cluster.') +param aksClusterKubernetesVersion string = '' + +@description('Optional. Specifies the administrator username of Linux virtual machines.') +param aksClusterAdminUsername string = 'azureuser' + +@description('Optional. Specifies the SSH RSA public key string for the Linux nodes.') +param aksClusterSshPublicKey string = '' + +@description('Optional. Information about a service principal identity for the cluster to use for manipulating Azure APIs.') +param aksServicePrincipalProfile object = {} + +@description('Optional. The client AAD application ID.') +param aadProfileClientAppID string = '' + +@description('Optional. The server AAD application ID.') +param aadProfileServerAppID string = '' + +@description('Optional. The server AAD application secret.') +param aadProfileServerAppSecret string = '' + +@description('Optional. Specifies the tenant ID of the Azure Active Directory used by the AKS cluster for authentication.') +param aadProfileTenantId string = subscription().tenantId + +@description('Optional. Specifies the AAD group object IDs that will have admin role of the cluster.') +param aadProfileAdminGroupObjectIDs array = [] + +@description('Optional. Specifies whether to enable managed AAD integration.') +param aadProfileManaged bool = true + +@description('Optional. Specifies whether to enable Azure RBAC for Kubernetes authorization.') +param aadProfileEnableAzureRBAC bool = true + +@description('Optional. If set to true, getting static credentials will be disabled for this cluster. This must only be used on Managed Clusters that are AAD enabled.') +param disableLocalAccounts bool = false + +@description('Optional. Name of the resource group containing agent pool nodes.') +param nodeResourceGroup string = '${resourceGroup().name}_aks_${name}_nodes' + +@description('Optional. IP ranges are specified in CIDR format, e.g. 137.117.106.88/29. This feature is not compatible with clusters that use Public IP Per Node, or clusters that are using a Basic Load Balancer.') +param authorizedIPRanges array = [] + +@description('Optional. Whether to disable run command for the cluster or not.') +param disableRunCommand bool = false + +@description('Optional. Specifies whether to create the cluster as a private cluster or not.') +param enablePrivateCluster bool = false + +@description('Optional. Whether to create additional public FQDN for private cluster or not.') +param enablePrivateClusterPublicFQDN bool = false + +@description('Optional. If AKS will create a Private DNS Zone in the Node Resource Group.') +param usePrivateDNSZone bool = false + +@description('Required. Properties of the primary agent pool.') +param primaryAgentPoolProfile array + +@description('Optional. Define one or more secondary/additional agent pools') +param agentPools array = [] + +@description('Optional. Specifies whether the httpApplicationRouting add-on is enabled or not.') +param httpApplicationRoutingEnabled bool = false + +@description('Optional. Specifies whether the aciConnectorLinux add-on is enabled or not.') +param aciConnectorLinuxEnabled bool = false + +@description('Optional. Specifies whether the azurepolicy add-on is enabled or not.') +param azurePolicyEnabled bool = true + +@description('Optional. Specifies the azure policy version to use.') +param azurePolicyVersion string = 'v2' + +@description('Optional. Specifies whether the kubeDashboard add-on is enabled or not.') +param kubeDashboardEnabled bool = false + +@description('Optional. Specifies whether the KeyvaultSecretsProvider add-on is enabled or not.') +param enableKeyvaultSecretsProvider bool = false + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies whether the KeyvaultSecretsProvider add-on uses secret rotation.') +param enableSecretRotation string = 'false' + +@description('Optional. Specifies the scan interval of the auto-scaler of the AKS cluster.') +param autoScalerProfileScanInterval string = '10s' + +@description('Optional. Specifies the scale down delay after add of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownDelayAfterAdd string = '10m' + +@description('Optional. Specifies the scale down delay after delete of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownDelayAfterDelete string = '20s' + +@description('Optional. Specifies scale down delay after failure of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownDelayAfterFailure string = '3m' + +@description('Optional. Specifies the scale down unneeded time of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownUnneededTime string = '10m' + +@description('Optional. Specifies the scale down unready time of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownUnreadyTime string = '20m' + +@description('Optional. Specifies the utilization threshold of the auto-scaler of the AKS cluster.') +param autoScalerProfileUtilizationThreshold string = '0.5' + +@description('Optional. Specifies the max graceful termination time interval in seconds for the auto-scaler of the AKS cluster.') +param autoScalerProfileMaxGracefulTerminationSec string = '600' + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies the balance of similar node groups for the auto-scaler of the AKS cluster.') +param autoScalerProfileBalanceSimilarNodeGroups string = 'false' + +@allowed([ + 'least-waste' + 'most-pods' + 'priority' + 'random' +]) +@description('Optional. Specifies the expand strategy for the auto-scaler of the AKS cluster.') +param autoScalerProfileExpander string = 'random' + +@description('Optional. Specifies the maximum empty bulk delete for the auto-scaler of the AKS cluster.') +param autoScalerProfileMaxEmptyBulkDelete string = '10' + +@description('Optional. Specifies the maximum node provisioning time for the auto-scaler of the AKS cluster. Values must be an integer followed by an "m". No unit of time other than minutes (m) is supported.') +param autoScalerProfileMaxNodeProvisionTime string = '15m' + +@description('Optional. Specifies the mximum total unready percentage for the auto-scaler of the AKS cluster. The maximum is 100 and the minimum is 0.') +param autoScalerProfileMaxTotalUnreadyPercentage string = '45' + +@description('Optional. For scenarios like burst/batch scale where you do not want CA to act before the kubernetes scheduler could schedule all the pods, you can tell CA to ignore unscheduled pods before they are a certain age. Values must be an integer followed by a unit ("s" for seconds, "m" for minutes, "h" for hours, etc).') +param autoScalerProfileNewPodScaleUpDelay string = '0s' + +@description('Optional. Specifies the ok total unready count for the auto-scaler of the AKS cluster.') +param autoScalerProfileOkTotalUnreadyCount string = '3' + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies if nodes with local storage should be skipped for the auto-scaler of the AKS cluster.') +param autoScalerProfileSkipNodesWithLocalStorage string = 'true' + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies if nodes with system pods should be skipped for the auto-scaler of the AKS cluster.') +param autoScalerProfileSkipNodesWithSystemPods string = 'true' + +@description('Optional. Running in Kubenet is disabled by default due to the security related nature of AAD Pod Identity and the risks of IP spoofing.') +param podIdentityProfileAllowNetworkPluginKubenet bool = false + +@description('Optional. Whether the pod identity addon is enabled.') +param podIdentityProfileEnable bool = false + +@description('Optional. The pod identities to use in the cluster.') +param podIdentityProfileUserAssignedIdentities array = [] + +@description('Optional. The pod identity exceptions to allow.') +param podIdentityProfileUserAssignedIdentityExceptions array = [] + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Specifies whether the OMS agent is enabled.') +param omsAgentEnabled bool = true + +@description('Optional. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'kube-apiserver' + 'kube-audit' + 'kube-controller-manager' + 'kube-scheduler' + 'cluster-autoscaler' +]) +param logsToEnable array = [ + 'kube-apiserver' + 'kube-audit' + 'kube-controller-manager' + 'kube-scheduler' + 'cluster-autoscaler' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? 'SystemAssigned' : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var aksClusterLinuxProfile = { + adminUsername: aksClusterAdminUsername + ssh: { + publicKeys: [ + { + keyData: aksClusterSshPublicKey + } + ] + } +} + +var lbProfile = { + managedOutboundIPs: { + count: managedOutboundIPCount + } + effectiveOutboundIPs: [] +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2021-10-01' = { + name: name + location: location + tags: (empty(tags) ? null : tags) + identity: identity + properties: { + kubernetesVersion: (empty(aksClusterKubernetesVersion) ? null : aksClusterKubernetesVersion) + dnsPrefix: aksClusterDnsPrefix + agentPoolProfiles: primaryAgentPoolProfile + sku: { + name: 'Basic' + tier: aksClusterSkuTier + } + linuxProfile: (empty(aksClusterSshPublicKey) ? null : aksClusterLinuxProfile) + servicePrincipalProfile: (empty(aksServicePrincipalProfile) ? null : aksServicePrincipalProfile) + addonProfiles: { + httpApplicationRouting: { + enabled: httpApplicationRoutingEnabled + } + omsagent: { + enabled: omsAgentEnabled && !empty(monitoringWorkspaceId) + config: { + logAnalyticsWorkspaceResourceID: !empty(monitoringWorkspaceId) ? any(monitoringWorkspaceId) : null + } + } + aciConnectorLinux: { + enabled: aciConnectorLinuxEnabled + } + azurepolicy: { + enabled: azurePolicyEnabled + config: { + version: azurePolicyVersion + } + } + kubeDashboard: { + enabled: kubeDashboardEnabled + } + azureKeyvaultSecretsProvider: { + enabled: enableKeyvaultSecretsProvider + config: { + enableSecretRotation: enableSecretRotation + } + } + } + enableRBAC: aadProfileEnableAzureRBAC + disableLocalAccounts: disableLocalAccounts + nodeResourceGroup: nodeResourceGroup + networkProfile: { + networkPlugin: !empty(aksClusterNetworkPlugin) ? any(aksClusterNetworkPlugin) : null + networkPolicy: !empty(aksClusterNetworkPolicy) ? any(aksClusterNetworkPolicy) : null + podCidr: !empty(aksClusterPodCidr) ? aksClusterPodCidr : null + serviceCidr: !empty(aksClusterServiceCidr) ? aksClusterServiceCidr : null + dnsServiceIP: !empty(aksClusterDnsServiceIP) ? aksClusterDnsServiceIP : null + dockerBridgeCidr: !empty(aksClusterDockerBridgeCidr) ? aksClusterDockerBridgeCidr : null + outboundType: aksClusterOutboundType + loadBalancerSku: aksClusterLoadBalancerSku + loadBalancerProfile: managedOutboundIPCount != 0 ? lbProfile : null + } + aadProfile: { + clientAppID: aadProfileClientAppID + serverAppID: aadProfileServerAppID + serverAppSecret: aadProfileServerAppSecret + managed: aadProfileManaged + enableAzureRBAC: aadProfileEnableAzureRBAC + adminGroupObjectIDs: aadProfileAdminGroupObjectIDs + tenantID: aadProfileTenantId + } + autoScalerProfile: { + 'balance-similar-node-groups': autoScalerProfileBalanceSimilarNodeGroups + 'expander': autoScalerProfileExpander + 'max-empty-bulk-delete': autoScalerProfileMaxEmptyBulkDelete + 'max-graceful-termination-sec': autoScalerProfileMaxGracefulTerminationSec + 'max-node-provision-time': autoScalerProfileMaxNodeProvisionTime + 'max-total-unready-percentage': autoScalerProfileMaxTotalUnreadyPercentage + 'new-pod-scale-up-delay': autoScalerProfileNewPodScaleUpDelay + 'ok-total-unready-count': autoScalerProfileOkTotalUnreadyCount + 'scale-down-delay-after-add': autoScalerProfileScaleDownDelayAfterAdd + 'scale-down-delay-after-delete': autoScalerProfileScaleDownDelayAfterDelete + 'scale-down-delay-after-failure': autoScalerProfileScaleDownDelayAfterFailure + 'scale-down-unneeded-time': autoScalerProfileScaleDownUnneededTime + 'scale-down-unready-time': autoScalerProfileScaleDownUnreadyTime + 'scale-down-utilization-threshold': autoScalerProfileUtilizationThreshold + 'scan-interval': autoScalerProfileScanInterval + 'skip-nodes-with-local-storage': autoScalerProfileSkipNodesWithLocalStorage + 'skip-nodes-with-system-pods': autoScalerProfileSkipNodesWithSystemPods + } + apiServerAccessProfile: { + authorizedIPRanges: authorizedIPRanges + disableRunCommand: disableRunCommand + enablePrivateCluster: enablePrivateCluster + enablePrivateClusterPublicFQDN: enablePrivateClusterPublicFQDN + privateDNSZone: usePrivateDNSZone ? 'system' : '' + } + podIdentityProfile: { + allowNetworkPluginKubenet: podIdentityProfileAllowNetworkPluginKubenet + enabled: podIdentityProfileEnable + userAssignedIdentities: podIdentityProfileUserAssignedIdentities + userAssignedIdentityExceptions: podIdentityProfileUserAssignedIdentityExceptions + } + } +} + +module managedCluster_agentPools 'agentPools/deploy.bicep' = [for (agentPool, index) in agentPools: { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-AgentPool-${index}' + params: { + managedClusterName: managedCluster.name + name: agentPool.name + availabilityZones: contains(agentPool, 'availabilityZones') ? agentPool.availabilityZones : [] + count: contains(agentPool, 'count') ? agentPool.count : 1 + sourceResourceId: contains(agentPool, 'sourceResourceId') ? agentPool.sourceResourceId : '' + enableAutoScaling: contains(agentPool, 'enableAutoScaling') ? agentPool.enableAutoScaling : false + enableEncryptionAtHost: contains(agentPool, 'enableEncryptionAtHost') ? agentPool.enableEncryptionAtHost : false + enableFIPS: contains(agentPool, 'enableFIPS') ? agentPool.enableFIPS : false + enableNodePublicIP: contains(agentPool, 'enableNodePublicIP') ? agentPool.enableNodePublicIP : false + enableUltraSSD: contains(agentPool, 'enableUltraSSD') ? agentPool.enableUltraSSD : false + gpuInstanceProfile: contains(agentPool, 'gpuInstanceProfile') ? agentPool.gpuInstanceProfile : '' + kubeletDiskType: contains(agentPool, 'kubeletDiskType') ? agentPool.kubeletDiskType : '' + maxCount: contains(agentPool, 'maxCount') ? agentPool.maxCount : -1 + maxPods: contains(agentPool, 'maxPods') ? agentPool.maxPods : -1 + minCount: contains(agentPool, 'minCount') ? agentPool.minCount : -1 + mode: contains(agentPool, 'mode') ? agentPool.mode : '' + nodeLabels: contains(agentPool, 'nodeLabels') ? agentPool.nodeLabels : {} + nodePublicIpPrefixId: contains(agentPool, 'nodePublicIpPrefixId') ? agentPool.nodePublicIpPrefixId : '' + nodeTaints: contains(agentPool, 'nodeTaints') ? agentPool.nodeTaints : [] + orchestratorVersion: contains(agentPool, 'orchestratorVersion') ? agentPool.orchestratorVersion : '' + osDiskSizeGB: contains(agentPool, 'osDiskSizeGB') ? agentPool.osDiskSizeGB : -1 + osDiskType: contains(agentPool, 'osDiskType') ? agentPool.osDiskType : '' + osSku: contains(agentPool, 'osSku') ? agentPool.osSku : '' + osType: contains(agentPool, 'osType') ? agentPool.osType : 'Linux' + podSubnetId: contains(agentPool, 'podSubnetId') ? agentPool.podSubnetId : '' + proximityPlacementGroupId: contains(agentPool, 'proximityPlacementGroupId') ? agentPool.proximityPlacementGroupId : '' + scaleDownMode: contains(agentPool, 'scaleDownMode') ? agentPool.scaleDownMode : 'Delete' + scaleSetEvictionPolicy: contains(agentPool, 'scaleSetEvictionPolicy') ? agentPool.scaleSetEvictionPolicy : 'Delete' + scaleSetPriority: contains(agentPool, 'scaleSetPriority') ? agentPool.scaleSetPriority : '' + spotMaxPrice: contains(agentPool, 'spotMaxPrice') ? agentPool.spotMaxPrice : -1 + tags: contains(agentPool, 'tags') ? agentPool.tags : {} + type: contains(agentPool, 'type') ? agentPool.type : '' + maxSurge: contains(agentPool, 'maxSurge') ? agentPool.maxSurge : '' + vmSize: contains(agentPool, 'vmSize') ? agentPool.vmSize : 'Standard_D2s_v3' + vnetSubnetId: contains(agentPool, 'vnetSubnetId') ? agentPool.vnetSubnetId : '' + workloadRuntime: contains(agentPool, 'workloadRuntime') ? agentPool.workloadRuntime : '' + } +}] + +resource managedCluster_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${managedCluster.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: managedCluster +} + +resource managedCluster_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${managedCluster.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: managedCluster +} + +module managedCluster_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: managedCluster.id + } +}] + +@description('The resource ID of the managed cluster') +output resourceId string = managedCluster.id + +@description('The resource group the managed cluster was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the managed cluster') +output name string = managedCluster.name + +@description('The control plane FQDN of the managed cluster') +output controlPlaneFQDN string = enablePrivateCluster ? managedCluster.properties.privateFQDN : managedCluster.properties.fqdn + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(managedCluster.identity, 'principalId') ? managedCluster.identity.principalId : '' + +@description('The Object ID of the AKS identity.') +output kubeletidentityObjectId string = contains(managedCluster.properties, 'identityProfile') ? contains(managedCluster.properties.identityProfile, 'kubeletidentity') ? managedCluster.properties.identityProfile.kubeletidentity.objectId : '' : '' + +@description('The Object ID of the OMS agent identity.') +output omsagentIdentityObjectId string = contains(managedCluster.properties, 'addonProfiles') ? contains(managedCluster.properties.addonProfiles, 'omsagent') ? contains(managedCluster.properties.addonProfiles.omsagent, 'identity') ? managedCluster.properties.addonProfiles.omsagent.identity.objectId : '' : '' : '' diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/readme.md b/carml/1.0.0/Microsoft.ContainerService/managedClusters/readme.md new file mode 100644 index 000000000..c2055cc15 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/readme.md @@ -0,0 +1,236 @@ +# Azure Kubernetes Services `[Microsoft.ContainerService/managedClusters]` + +This module deploys Azure Kubernetes Cluster (AKS). + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ContainerService/managedClusters` | 2021-10-01 | +| `Microsoft.ContainerService/managedClusters/agentPools` | 2021-08-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `aadProfileAdminGroupObjectIDs` | array | `[]` | | Optional. Specifies the AAD group object IDs that will have admin role of the cluster. | +| `aadProfileClientAppID` | string | | | Optional. The client AAD application ID. | +| `aadProfileEnableAzureRBAC` | bool | `True` | | Optional. Specifies whether to enable Azure RBAC for Kubernetes authorization. | +| `aadProfileManaged` | bool | `True` | | Optional. Specifies whether to enable managed AAD integration. | +| `aadProfileServerAppID` | string | | | Optional. The server AAD application ID. | +| `aadProfileServerAppSecret` | string | | | Optional. The server AAD application secret. | +| `aadProfileTenantId` | string | `[subscription().tenantId]` | | Optional. Specifies the tenant ID of the Azure Active Directory used by the AKS cluster for authentication. | +| `aciConnectorLinuxEnabled` | bool | `False` | | Optional. Specifies whether the aciConnectorLinux add-on is enabled or not. | +| `agentPools` | _[agentPools](agentPools/readme.md)_ array | `[]` | | Optional. Define one or more secondary/additional agent pools | +| `aksClusterAdminUsername` | string | `azureuser` | | Optional. Specifies the administrator username of Linux virtual machines. | +| `aksClusterDnsPrefix` | string | `[parameters('name')]` | | Optional. Specifies the DNS prefix specified when creating the managed cluster. | +| `aksClusterDnsServiceIP` | string | | | Optional. Specifies the IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr. | +| `aksClusterDockerBridgeCidr` | string | | | Optional. Specifies the CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range. | +| `aksClusterKubernetesVersion` | string | | | Optional. Version of Kubernetes specified when creating the managed cluster. | +| `aksClusterLoadBalancerSku` | string | `standard` | `[basic, standard]` | Optional. Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools. | +| `aksClusterNetworkPlugin` | string | | `[, azure, kubenet]` | Optional. Specifies the network plugin used for building Kubernetes network. - azure or kubenet. | +| `aksClusterNetworkPolicy` | string | | `[, azure, calico]` | Optional. Specifies the network policy used for building Kubernetes network. - calico or azure | +| `aksClusterOutboundType` | string | `loadBalancer` | `[loadBalancer, userDefinedRouting]` | Optional. Specifies outbound (egress) routing method. - loadBalancer or userDefinedRouting. | +| `aksClusterPodCidr` | string | | | Optional. Specifies the CIDR notation IP range from which to assign pod IPs when kubenet is used. | +| `aksClusterServiceCidr` | string | | | Optional. A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges. | +| `aksClusterSkuTier` | string | `Free` | `[Free, Paid]` | Optional. Tier of a managed cluster SKU. - Free or Paid | +| `aksClusterSshPublicKey` | string | | | Optional. Specifies the SSH RSA public key string for the Linux nodes. | +| `aksServicePrincipalProfile` | object | `{object}` | | Optional. Information about a service principal identity for the cluster to use for manipulating Azure APIs. | +| `authorizedIPRanges` | array | `[]` | | Optional. IP ranges are specified in CIDR format, e.g. 137.117.106.88/29. This feature is not compatible with clusters that use Public IP Per Node, or clusters that are using a Basic Load Balancer. | +| `autoScalerProfileBalanceSimilarNodeGroups` | string | `false` | `[false, true]` | Optional. Specifies the balance of similar node groups for the auto-scaler of the AKS cluster. | +| `autoScalerProfileExpander` | string | `random` | `[least-waste, most-pods, priority, random]` | Optional. Specifies the expand strategy for the auto-scaler of the AKS cluster. | +| `autoScalerProfileMaxEmptyBulkDelete` | string | `10` | | Optional. Specifies the maximum empty bulk delete for the auto-scaler of the AKS cluster. | +| `autoScalerProfileMaxGracefulTerminationSec` | string | `600` | | Optional. Specifies the max graceful termination time interval in seconds for the auto-scaler of the AKS cluster. | +| `autoScalerProfileMaxNodeProvisionTime` | string | `15m` | | Optional. Specifies the maximum node provisioning time for the auto-scaler of the AKS cluster. Values must be an integer followed by an "m". No unit of time other than minutes (m) is supported. | +| `autoScalerProfileMaxTotalUnreadyPercentage` | string | `45` | | Optional. Specifies the mximum total unready percentage for the auto-scaler of the AKS cluster. The maximum is 100 and the minimum is 0. | +| `autoScalerProfileNewPodScaleUpDelay` | string | `0s` | | Optional. For scenarios like burst/batch scale where you do not want CA to act before the kubernetes scheduler could schedule all the pods, you can tell CA to ignore unscheduled pods before they are a certain age. Values must be an integer followed by a unit ("s" for seconds, "m" for minutes, "h" for hours, etc). | +| `autoScalerProfileOkTotalUnreadyCount` | string | `3` | | Optional. Specifies the ok total unready count for the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownDelayAfterAdd` | string | `10m` | | Optional. Specifies the scale down delay after add of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownDelayAfterDelete` | string | `20s` | | Optional. Specifies the scale down delay after delete of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownDelayAfterFailure` | string | `3m` | | Optional. Specifies scale down delay after failure of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownUnneededTime` | string | `10m` | | Optional. Specifies the scale down unneeded time of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownUnreadyTime` | string | `20m` | | Optional. Specifies the scale down unready time of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScanInterval` | string | `10s` | | Optional. Specifies the scan interval of the auto-scaler of the AKS cluster. | +| `autoScalerProfileSkipNodesWithLocalStorage` | string | `true` | `[false, true]` | Optional. Specifies if nodes with local storage should be skipped for the auto-scaler of the AKS cluster. | +| `autoScalerProfileSkipNodesWithSystemPods` | string | `true` | `[false, true]` | Optional. Specifies if nodes with system pods should be skipped for the auto-scaler of the AKS cluster. | +| `autoScalerProfileUtilizationThreshold` | string | `0.5` | | Optional. Specifies the utilization threshold of the auto-scaler of the AKS cluster. | +| `azurePolicyEnabled` | bool | `True` | | Optional. Specifies whether the azurepolicy add-on is enabled or not. | +| `azurePolicyVersion` | string | `v2` | | Optional. Specifies the azure policy version to use. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `disableLocalAccounts` | bool | `False` | | Optional. If set to true, getting static credentials will be disabled for this cluster. This must only be used on Managed Clusters that are AAD enabled. | +| `disableRunCommand` | bool | `False` | | Optional. Whether to disable run command for the cluster or not. | +| `enableKeyvaultSecretsProvider` | bool | `False` | | Optional. Specifies whether the KeyvaultSecretsProvider add-on is enabled or not. | +| `enablePrivateCluster` | bool | `False` | | Optional. Specifies whether to create the cluster as a private cluster or not. | +| `enablePrivateClusterPublicFQDN` | bool | `False` | | Optional. Whether to create additional public FQDN for private cluster or not. | +| `enableSecretRotation` | string | `false` | `[false, true]` | Optional. Specifies whether the KeyvaultSecretsProvider add-on uses secret rotation. | +| `httpApplicationRoutingEnabled` | bool | `False` | | Optional. Specifies whether the httpApplicationRouting add-on is enabled or not. | +| `kubeDashboardEnabled` | bool | `False` | | Optional. Specifies whether the kubeDashboard add-on is enabled or not. | +| `location` | string | `[resourceGroup().location]` | | Optional. Specifies the location of AKS cluster. It picks up Resource Group's location by default. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[kube-apiserver, kube-audit, kube-controller-manager, kube-scheduler, cluster-autoscaler]` | `[kube-apiserver, kube-audit, kube-controller-manager, kube-scheduler, cluster-autoscaler]` | Optional. The name of logs that will be streamed. | +| `managedOutboundIPCount` | int | `0` | | Optional. Outbound IP Count for the Load balancer. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `monitoringWorkspaceId` | string | | | Optional. Resource ID of the monitoring log analytics workspace. | +| `name` | string | | | Required. Specifies the name of the AKS cluster. | +| `nodeResourceGroup` | string | `[format('{0}_aks_{1}_nodes', resourceGroup().name, parameters('name'))]` | | Optional. Name of the resource group containing agent pool nodes. | +| `omsAgentEnabled` | bool | `True` | | Optional. Specifies whether the OMS agent is enabled. | +| `podIdentityProfileAllowNetworkPluginKubenet` | bool | `False` | | Optional. Running in Kubenet is disabled by default due to the security related nature of AAD Pod Identity and the risks of IP spoofing. | +| `podIdentityProfileEnable` | bool | `False` | | Optional. Whether the pod identity addon is enabled. | +| `podIdentityProfileUserAssignedIdentities` | array | `[]` | | Optional. The pod identities to use in the cluster. | +| `podIdentityProfileUserAssignedIdentityExceptions` | array | `[]` | | Optional. The pod identity exceptions to allow. | +| `primaryAgentPoolProfile` | array | | | Required. Properties of the primary agent pool. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `usePrivateDNSZone` | bool | `False` | | Optional. If AKS will create a Private DNS Zone in the Node Resource Group. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `identity` + +See also + +```json +"identity": { + "value": { + "type": "string", + "userAssignedIdentities": {} + } +} +``` + +### Parameter Usage: `aksServicePrincipalProfile` + +See also + +```json +"aksServicePrincipalProfile": { + "value": { + "clientId": "string", + "secret": "string" + } +} +``` + +### Parameter Usage: `primaryAgentPoolProfile` + +Provide values for primary agent pool as needed. +For available properties check + +```json +"primaryAgentPoolProfile": { + "value": [ + { + "name": "poolname", + "vmSize": "Standard_DS3_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 5, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1", + "2", + "3" + ], + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "System", + "vnetSubnetID": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet", + "tags": { + "Owner": "test.user@testcompany.com", + "BusinessUnit": "IaCs", + "Environment": "PROD", + "Region": "USEast" + } + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `controlPlaneFQDN` | string | The control plane FQDN of the managed cluster | +| `kubeletidentityObjectId` | string | The Object ID of the AKS identity. | +| `name` | string | The name of the managed cluster | +| `omsagentIdentityObjectId` | string | The Object ID of the OMS agent identity. | +| `resourceGroupName` | string | The resource group the managed cluster was deployed into | +| `resourceId` | string | The resource ID of the managed cluster | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Managedclusters](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerService/2021-10-01/managedClusters) +- [Managedclusters/Agentpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerService/2021-08-01/managedClusters/agentPools) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.ContainerService/managedClusters/version.json b/carml/1.0.0/Microsoft.ContainerService/managedClusters/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ContainerService/managedClusters/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/carml/1.0.0/Microsoft.DataFactory/factories/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b9a0076ab --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/.bicep/nested_rbac.bicep @@ -0,0 +1,33 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Data Factory Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(dataFactory.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: dataFactory +}] diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/.parameters/parameters.json b/carml/1.0.0/Microsoft.DataFactory/factories/.parameters/parameters.json new file mode 100644 index 000000000..8b5e31f73 --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/.parameters/parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-adf-001" + }, + "managedVirtualNetworkName": { + "value": "default" + }, + "integrationRuntime": { + "value": { + "name": "AutoResolveIntegrationRuntime", + "type": "Managed", + "managedVirtualNetworkName": "default", + "typeProperties": { + "computeProperties": { + "location": "AutoResolve" + } + } + } + }, + "publicNetworkAccess": { + "value": true + }, + "gitConfigureLater": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/deploy.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/deploy.bicep new file mode 100644 index 000000000..d45404efb --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/deploy.bicep @@ -0,0 +1,214 @@ +@description('Required. The name of the Azure Factory to create') +param name string + +@description('Optional. The name of the Managed Virtual Network') +param managedVirtualNetworkName string = '' + +@description('Optional. The object for the configuration of a Integration Runtime') +param integrationRuntime object = {} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Enable or disable public network access.') +param publicNetworkAccess bool = true + +@description('Optional. Boolean to define whether or not to configure git during template deployment.') +param gitConfigureLater bool = true + +@description('Optional. Repository type - can be \'FactoryVSTSConfiguration\' or \'FactoryGitHubConfiguration\'. Default is \'FactoryVSTSConfiguration\'.') +param gitRepoType string = 'FactoryVSTSConfiguration' + +@description('Optional. The account name.') +param gitAccountName string = '' + +@description('Optional. The project name. Only relevant for \'FactoryVSTSConfiguration\'.') +param gitProjectName string = '' + +@description('Optional. The repository name.') +param gitRepositoryName string = '' + +@description('Optional. The collaboration branch name. Default is \'main\'.') +param gitCollaborationBranch string = 'main' + +@description('Optional. The root folder path name. Default is \'/\'.') +param gitRootFolder string = '/' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ActivityRuns' + 'PipelineRuns' + 'TriggerRuns' + 'SSISPackageEventMessages' + 'SSISPackageExecutableStatistics' + 'SSISPackageEventMessageContext' + 'SSISPackageExecutionComponentPhases' + 'SSISPackageExecutionDataStatistics' + 'SSISIntegrationRuntimeLogs' +]) +param logsToEnable array = [ + 'ActivityRuns' + 'PipelineRuns' + 'TriggerRuns' + 'SSISPackageEventMessages' + 'SSISPackageExecutableStatistics' + 'SSISPackageEventMessageContext' + 'SSISPackageExecutionComponentPhases' + 'SSISPackageExecutionDataStatistics' + 'SSISIntegrationRuntimeLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + repoConfiguration: bool(gitConfigureLater) ? null : json('{"type": "${gitRepoType}","accountName": "${gitAccountName}","repositoryName": "${gitRepositoryName}",${((gitRepoType == 'FactoryVSTSConfiguration') ? '"projectName": "${gitProjectName}",' : '')}"collaborationBranch": "${gitCollaborationBranch}","rootFolder": "${gitRootFolder}"}') + publicNetworkAccess: bool(publicNetworkAccess) ? 'Enabled' : 'Disabled' + } +} + +module dataFactory_managedVirtualNetwork 'managedVirtualNetwork/deploy.bicep' = if (!empty(managedVirtualNetworkName)) { + name: '${uniqueString(deployment().name, location)}-DataFactory-ManagedVNet' + params: { + name: managedVirtualNetworkName + dataFactoryName: dataFactory.name + } +} + +module dataFactory_integrationRuntime 'integrationRuntime/deploy.bicep' = if (!empty(integrationRuntime)) { + name: '${uniqueString(deployment().name, location)}-DataFactory-IntegrationRuntime' + params: { + dataFactoryName: dataFactory.name + name: integrationRuntime.name + type: integrationRuntime.type + managedVirtualNetworkName: contains(integrationRuntime, 'managedVirtualNetworkName') ? integrationRuntime.managedVirtualNetworkName : '' + typeProperties: integrationRuntime.typeProperties + } + dependsOn: [ + dataFactory_managedVirtualNetwork + ] +} + +resource dataFactory_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${dataFactory.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: dataFactory +} + +resource dataFactory_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${dataFactory.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: dataFactory +} + +module dataFactory_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DataFactory-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: dataFactory.id + } +}] + +@description('The Name of the Azure Data Factory instance.') +output name string = dataFactory.name + +@description('The Resource ID of the Data factory.') +output resourceId string = dataFactory.id + +@description('The name of the Resource Group with the Data factory.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(dataFactory.identity, 'principalId') ? dataFactory.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/deploy.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/deploy.bicep new file mode 100644 index 000000000..d1dda4351 --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/deploy.bicep @@ -0,0 +1,54 @@ +@description('Required. The name of the Azure Data Factory') +param dataFactoryName string + +@description('Required. The name of the Integration Runtime') +param name string + +@allowed([ + 'Managed' + 'SelfHosted' +]) +@description('Required. The type of Integration Runtime') +param type string + +@description('Optional. The name of the Managed Virtual Network if using type "Managed" ') +param managedVirtualNetworkName string = '' + +@description('Required. Integration Runtime type properties.') +param typeProperties object + +@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 managedVirtualNetwork_var = { + referenceName: type == 'Managed' ? managedVirtualNetworkName : null + type: type == 'Managed' ? 'ManagedVirtualNetworkReference' : null +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' existing = { + name: dataFactoryName +} + +resource integrationRuntime 'Microsoft.DataFactory/factories/integrationRuntimes@2018-06-01' = { + name: name + parent: dataFactory + properties: { + type: type + managedVirtualNetwork: type == 'Managed' ? managedVirtualNetwork_var : null + typeProperties: typeProperties + } +} + +@description('The name of the Resource Group the Integration Runtime was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Integration Runtime.') +output name string = integrationRuntime.name + +@description('The resource ID of the Integration Runtime.') +output resourceId string = integrationRuntime.id diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/readme.md b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/readme.md new file mode 100644 index 000000000..947227aae --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/readme.md @@ -0,0 +1,45 @@ +# Data Factory Integration RunTimes `[Microsoft.DataFactory/factories/integrationRuntime]` + +This module deploys a Managed or Self-Hosted Integration Runtime for an Azure Data Factory + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DataFactory/factories/integrationRuntimes` | 2018-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `dataFactoryName` | string | | | Required. The name of the Azure Data Factory | +| `managedVirtualNetworkName` | string | | | Optional. The name of the Managed Virtual Network if using type "Managed" | +| `name` | string | | | Required. The name of the Integration Runtime | +| `type` | string | | `[Managed, SelfHosted]` | Required. The type of Integration Runtime | +| `typeProperties` | object | | | Required. Integration Runtime type properties. | + +### Parameter Usage: [`typeProperties`](https://docs.microsoft.com/en-us/azure/templates/microsoft.datafactory/factories/integrationruntimes?tabs=bicep#integrationruntime-objects) + +```json +"typeProperties": { + "value": { + "computeProperties": { + "location": "AutoResolve" + } + } +} + +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Integration Runtime. | +| `resourceGroupName` | string | The name of the Resource Group the Integration Runtime was created in. | +| `resourceId` | string | The resource ID of the Integration Runtime. | + +## Template references + +- [Factories/Integrationruntimes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/integrationRuntimes) diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/version.json b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/integrationRuntime/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/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/deploy.bicep b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/deploy.bicep new file mode 100644 index 000000000..cac060cee --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/deploy.bicep @@ -0,0 +1,32 @@ +@description('Required. The name of the Azure Data Factory') +param dataFactoryName string + +@description('Required. The name of the Managed Virtual Network') +param name string + +@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 dataFactory 'Microsoft.DataFactory/factories@2018-06-01' existing = { + name: dataFactoryName +} + +resource managedVirtualNetwork 'Microsoft.DataFactory/factories/managedVirtualNetworks@2018-06-01' = { + name: name + parent: dataFactory + properties: {} +} + +@description('The name of the Resource Group the Managed Virtual Network was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Managed Virtual Network.') +output name string = managedVirtualNetwork.name + +@description('The resource ID of the Managed Virtual Network.') +output resourceId string = managedVirtualNetwork.id diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/readme.md b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/readme.md new file mode 100644 index 000000000..2e8e348dd --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/readme.md @@ -0,0 +1,29 @@ +# Data Factory Managed Virtual Network `[Microsoft.DataFactory/factories/managedVirtualNetwork]` + +This module deploys a Managed Virtual Network for an Azure Data Factory + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DataFactory/factories/managedVirtualNetworks` | 2018-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `dataFactoryName` | string | | | Required. The name of the Azure Data Factory | +| `name` | string | | | Required. The name of the Managed Virtual Network | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Managed Virtual Network. | +| `resourceGroupName` | string | The name of the Resource Group the Managed Virtual Network was created in. | +| `resourceId` | string | The resource ID of the Managed Virtual Network. | + +## Template references + +- [Factories/Managedvirtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/managedVirtualNetworks) diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/version.json b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/managedVirtualNetwork/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/carml/1.0.0/Microsoft.DataFactory/factories/readme.md b/carml/1.0.0/Microsoft.DataFactory/factories/readme.md new file mode 100644 index 000000000..4e304a0a2 --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/readme.md @@ -0,0 +1,112 @@ +# Data Factories `[Microsoft.DataFactory/factories]` + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DataFactory/factories` | 2018-06-01 | +| `Microsoft.DataFactory/factories/integrationRuntimes` | 2018-06-01 | +| `Microsoft.DataFactory/factories/managedVirtualNetworks` | 2018-06-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-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 | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `gitAccountName` | string | | | Optional. The account name. | +| `gitCollaborationBranch` | string | `main` | | Optional. The collaboration branch name. Default is 'main'. | +| `gitConfigureLater` | bool | `True` | | Optional. Boolean to define whether or not to configure git during template deployment. | +| `gitProjectName` | string | | | Optional. The project name. Only relevant for 'FactoryVSTSConfiguration'. | +| `gitRepositoryName` | string | | | Optional. The repository name. | +| `gitRepoType` | string | `FactoryVSTSConfiguration` | | Optional. Repository type - can be 'FactoryVSTSConfiguration' or 'FactoryGitHubConfiguration'. Default is 'FactoryVSTSConfiguration'. | +| `gitRootFolder` | string | `/` | | Optional. The root folder path name. Default is '/'. | +| `integrationRuntime` | _[integrationRuntime](integrationRuntime/readme.md)_ object | `{object}` | | Optional. The object for the configuration of a Integration Runtime | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ActivityRuns, PipelineRuns, TriggerRuns, SSISPackageEventMessages, SSISPackageExecutableStatistics, SSISPackageEventMessageContext, SSISPackageExecutionComponentPhases, SSISPackageExecutionDataStatistics, SSISIntegrationRuntimeLogs]` | `[ActivityRuns, PipelineRuns, TriggerRuns, SSISPackageEventMessages, SSISPackageExecutableStatistics, SSISPackageEventMessageContext, SSISPackageExecutionComponentPhases, SSISPackageExecutionDataStatistics, SSISIntegrationRuntimeLogs]` | Optional. The name of logs that will be streamed. | +| `managedVirtualNetworkName` | string | | | Optional. The name of the Managed Virtual Network | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the Azure Factory to create | +| `publicNetworkAccess` | bool | `True` | | Optional. Enable or disable public network access. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the Azure Data Factory instance. | +| `resourceGroupName` | string | The name of the Resource Group with the Data factory. | +| `resourceId` | string | The Resource ID of the Data factory. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Factories](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories) +- [Factories/Integrationruntimes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/integrationRuntimes) +- [Factories/Managedvirtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/managedVirtualNetworks) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.DataFactory/factories/version.json b/carml/1.0.0/Microsoft.DataFactory/factories/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DataFactory/factories/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/carml/1.0.0/Microsoft.Databricks/workspaces/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Databricks/workspaces/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Databricks/workspaces/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Databricks/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Databricks/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..fb6f95154 --- /dev/null +++ b/carml/1.0.0/Microsoft.Databricks/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.Databricks/workspaces@2018-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: workspace +}] diff --git a/carml/1.0.0/Microsoft.Databricks/workspaces/.parameters/parameters.json b/carml/1.0.0/Microsoft.Databricks/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..7d3ba311e --- /dev/null +++ b/carml/1.0.0/Microsoft.Databricks/workspaces/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-adb-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Databricks/workspaces/deploy.bicep b/carml/1.0.0/Microsoft.Databricks/workspaces/deploy.bicep new file mode 100644 index 000000000..efe13ab5c --- /dev/null +++ b/carml/1.0.0/Microsoft.Databricks/workspaces/deploy.bicep @@ -0,0 +1,148 @@ +@description('Required. The name of the Azure Databricks workspace to create') +param name string + +@description('Optional. The managed resource group ID') +param managedResourceGroupId string = '' + +@description('Optional. The pricing tier of workspace') +@allowed([ + 'trial' + 'standard' + 'premium' +]) +param pricingTier string = 'premium' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. The workspace\'s custom parameters.') +param workspaceParameters object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'dbfs' + 'clusters' + 'accounts' + 'jobs' + 'notebook' + 'ssh' + 'workspace' + 'secrets' + 'sqlPermissions' + 'instancePools' +]) +param logsToEnable array = [ + 'dbfs' + 'clusters' + 'accounts' + 'jobs' + 'notebook' + 'ssh' + 'workspace' + 'secrets' + 'sqlPermissions' + 'instancePools' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var managedResourceGroupName = '${name}-rg' +var managedResourceGroupId_var = '${subscription().id}/resourceGroups/${managedResourceGroupName}' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource workspace 'Microsoft.Databricks/workspaces@2018-04-01' = { + name: name + location: location + tags: tags + sku: { + name: pricingTier + } + properties: { + managedResourceGroupId: (empty(managedResourceGroupId) ? managedResourceGroupId_var : managedResourceGroupId) + parameters: workspaceParameters + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${workspace.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DataBricks-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The name of the deployed databricks workspace') +output name string = workspace.name + +@description('The resource ID of the deployed databricks workspace') +output resourceId string = workspace.id + +@description('The resource group of the deployed databricks workspace') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Databricks/workspaces/readme.md b/carml/1.0.0/Microsoft.Databricks/workspaces/readme.md new file mode 100644 index 000000000..a315da565 --- /dev/null +++ b/carml/1.0.0/Microsoft.Databricks/workspaces/readme.md @@ -0,0 +1,117 @@ +# Azure Databricks `[Microsoft.Databricks/workspaces]` + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Databricks/workspaces` | 2018-04-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-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 | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[dbfs, clusters, accounts, jobs, notebook, ssh, workspace, secrets, sqlPermissions, instancePools]` | `[dbfs, clusters, accounts, jobs, notebook, ssh, workspace, secrets, sqlPermissions, instancePools]` | Optional. The name of logs that will be streamed. | +| `managedResourceGroupId` | string | | | Optional. The managed resource group ID | +| `name` | string | | | Required. The name of the Azure Databricks workspace to create | +| `pricingTier` | string | `premium` | `[trial, standard, premium]` | Optional. The pricing tier of workspace | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `workspaceParameters` | object | `{object}` | | Optional. The workspace's custom parameters. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `customPublicSubnetName` and `customPrivateSubnetName` + +- Require Network Security Groups attached to the subnets + - The rule don't have to be set, they are set through the deployment + +- The two subnets also need the delegation to service `Microsoft.Databricks/workspaces` + +### Parameter Usage: `workspaceParameters` + +- Include only those elements (e.g. amlWorkspaceId) as object if specified, otherwise remove it + +```json +"workspaceParameters": { + "value": { + "amlWorkspaceId": { + "value": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.MachineLearningServices/workspaces/xxx" + }, + "customVirtualNetworkId": { + "value": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx" + }, + "customPublicSubnetName": { + "value": "xxx" + }, + "customPrivateSubnetName": { + "value": "xxx" + }, + "enableNoPublicIp": { + "value": true + } + } + } +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed databricks workspace | +| `resourceGroupName` | string | The resource group of the deployed databricks workspace | +| `resourceId` | string | The resource ID of the deployed databricks workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Databricks/2018-04-01/workspaces) diff --git a/carml/1.0.0/Microsoft.Databricks/workspaces/version.json b/carml/1.0.0/Microsoft.Databricks/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Databricks/workspaces/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/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..cb0e1d3d0 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63') + 'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b') + 'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationgroups@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appGroup.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: appGroup +}] diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/min.parameters.json new file mode 100644 index 000000000..ecf7a145e --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/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": { + "name": { + "value": "<>-az-avdag-min-001" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "adp-<>-az-avdhp-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json new file mode 100644 index 000000000..2b43fed10 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdag-x-001" + }, + "location": { + "value": "westeurope" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "adp-<>-az-avdhp-x-001" + }, + "friendlyName": { + "value": "Remote Applications 1" + }, + "description": { + "value": "This is my first Remote Applications bundle" + }, + "applications": { + "value": [ + { + "name": "notepad", + "description": "Notepad by ARM template", + "friendlyName": "Notepad", + "filePath": "C:\\Windows\\System32\\notepad.exe", + "commandLineSetting": "DoNotAllow", + "commandLineArguments": "", + "showInPortal": true, + "iconPath": "C:\\Windows\\System32\\notepad.exe", + "iconIndex": 0 + }, + { + "name": "wordpad", + "filePath": "C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe", + "friendlyName": "Wordpad" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep new file mode 100644 index 000000000..c2f7a8d0c --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep @@ -0,0 +1,70 @@ +@sys.description('Required. Name of the Application Group to create the application(s) in.') +param appGroupName string + +@sys.description('Required. Name of the Application to be created in the Application Group.') +param name string + +@sys.description('Optional. Description of Application..') +param description string = '' + +@sys.description('Required. Friendly name of Application..') +param friendlyName string + +@sys.description('Required. Specifies a path for the executable file for the application.') +param filePath string + +@allowed([ + 'Allow' + 'DoNotAllow' + 'Require' +]) +@sys.description('Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all.') +param commandLineSetting string = 'DoNotAllow' + +@sys.description('Optional. Command-Line Arguments for Application.') +param commandLineArguments string = '' + +@sys.description('Optional. Specifies whether to show the RemoteApp program in the RD Web Access server.') +param showInPortal bool = false + +@sys.description('Optional. Path to icon.') +param iconPath string = '' + +@sys.description('Optional. Index of the icon.') +param iconIndex int = 0 + +@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 applicationGroup 'Microsoft.DesktopVirtualization/applicationGroups@2021-09-03-preview' existing = { + name: appGroupName +} + +resource application 'Microsoft.DesktopVirtualization/applicationGroups/applications@2021-07-12' = { + name: name + parent: applicationGroup + properties: { + description: description + friendlyName: friendlyName + filePath: filePath + commandLineSetting: commandLineSetting + commandLineArguments: commandLineArguments + showInPortal: showInPortal + iconPath: iconPath + iconIndex: iconIndex + } +} + +@sys.description('The resource ID of the deployed Application.') +output applicationResourceIds string = application.id + +@sys.description('The name of the Resource Group the AVD Application was created in.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The Name of the Application Group to register the Application in.') +output name string = appGroupName diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md new file mode 100644 index 000000000..be7ede508 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md @@ -0,0 +1,37 @@ +# AVD Applications `[Microsoft.DesktopVirtualization/applicationGroups/applications]` + +This module deploys AVD Applications. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | 2021-07-12 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appGroupName` | string | | | Required. Name of the Application Group to create the application(s) in. | +| `commandLineArguments` | string | | | Optional. Command-Line Arguments for Application. | +| `commandLineSetting` | string | `DoNotAllow` | `[Allow, DoNotAllow, Require]` | Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `description` | string | | | Optional. Description of Application.. | +| `filePath` | string | | | Required. Specifies a path for the executable file for the application. | +| `friendlyName` | string | | | Required. Friendly name of Application.. | +| `iconIndex` | int | | | Optional. Index of the icon. | +| `iconPath` | string | | | Optional. Path to icon. | +| `name` | string | | | Required. Name of the Application to be created in the Application Group. | +| `showInPortal` | bool | | | Optional. Specifies whether to show the RemoteApp program in the RD Web Access server. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationResourceIds` | string | The resource ID of the deployed Application. | +| `name` | string | The Name of the Application Group to register the Application in. | +| `resourceGroupName` | string | The name of the Resource Group the AVD Application was created in. | + +## Template references + +- [Applicationgroups/Applications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups/applications) diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/version.json b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/applications/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/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep new file mode 100644 index 000000000..d789f8d86 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep @@ -0,0 +1,156 @@ +@sys.description('Required. Name of the Application Group to create this application in.') +@minLength(1) +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop') +@allowed([ + 'RemoteApp' + 'Desktop' +]) +param applicationGroupType string + +@sys.description('Required. Name of the Host Pool to be linked to this Application Group.') +param hostpoolName string + +@sys.description('Optional. The friendly name of the Application Group to be created.') +param friendlyName string = '' + +@sys.description('Optional. The description of the Application Group to be created.') +param description string = '' + +@sys.description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@sys.description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@sys.description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@sys.description('Optional. Resource ID of log analytics.') +param diagnosticWorkspaceId string = '' + +@sys.description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@sys.description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@sys.description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@sys.description('Optional. Tags of the resource.') +param tags object = {} + +@sys.description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@sys.description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' +]) +param logsToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' +] + +@sys.description('Optional. List of applications to be created in the Application Group.') +param applications array = [] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource appGroup_hostpool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: hostpoolName +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationgroups@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + hostPoolArmPath: appGroup_hostpool.id + friendlyName: friendlyName + description: description + applicationGroupType: applicationGroupType + } +} + +resource appGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appGroup.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appGroup +} + +resource appGroup_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${appGroup.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: appGroup +} + +module appGroup_applications 'applications/deploy.bicep' = [for (application, index) in applications: { + name: '${uniqueString(deployment().name, location)}-AppGroup-App-${index}' + params: { + name: application.name + appGroupName: appGroup.name + description: contains(application, 'description') ? application.description : '' + friendlyName: contains(application, 'friendlyName') ? application.friendlyName : appGroup.name + filePath: application.filePath + commandLineSetting: contains(application, 'commandLineSetting') ? application.commandLineSetting : 'DoNotAllow' + commandLineArguments: contains(application, 'commandLineArguments') ? application.commandLineArguments : '' + showInPortal: contains(application, 'showInPortal') ? application.showInPortal : false + iconPath: contains(application, 'iconPath') ? application.iconPath : application.filePath + iconIndex: contains(application, 'iconIndex') ? application.iconIndex : 0 + } +}] + +module appGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGroup-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appGroup.id + } +}] + +@sys.description('The resource ID of the AVD application group') +output resourceId string = appGroup.id + +@sys.description('The resource group the AVD application group was deployed into') +output resourceGroupName string = resourceGroup().name + +@sys.description('The name of the AVD application group') +output name string = appGroup.name diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/readme.md b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/readme.md new file mode 100644 index 000000000..ada8ed217 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/readme.md @@ -0,0 +1,90 @@ +# AVD Application Groups `[Microsoft.DesktopVirtualization/applicationgroups]` + +This module deploys an Azure virtual desktop application group. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/applicationGroups` | 2021-07-12 | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `applicationGroupType` | string | | `[RemoteApp, Desktop]` | Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop | +| `applications` | _[applications](applications/readme.md)_ array | `[]` | | Optional. List of applications to be created in the Application Group. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `description` | string | | | Optional. The description of the Application Group to be created. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of log analytics. | +| `friendlyName` | string | | | Optional. The friendly name of the Application Group to be created. | +| `hostpoolName` | string | | | Required. Name of the Host Pool to be linked to this Application Group. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[Checkpoint, Error, Management]` | `[Checkpoint, Error, Management]` | Optional. The name of logs that will be streamed. | +| `name` | string | | | Required. Name of the Application Group to create this application in. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD application group | +| `resourceGroupName` | string | The resource group the AVD application group was deployed into | +| `resourceId` | string | The resource ID of the AVD application group | + +## Template references + +- [Applicationgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups) +- [Applicationgroups/Applications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups/applications) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/version.json b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/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/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..92fa48424 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep @@ -0,0 +1,41 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Host Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc') + 'Desktop Virtualization Host Pool Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Session Host Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408') + 'Desktop Virtualization User Session Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(hostPool.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: hostPool +}] diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json new file mode 100644 index 000000000..ba8ef0e1f --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdhp-x-001" + }, + "location": { + "value": "westeurope" + }, + "hostpoolFriendlyName": { + "value": "AVDv2" + }, + "hostpoolDescription": { + "value": "My first AVD Host Pool" + }, + "hostpoolType": { + "value": "Pooled" + }, + "personalDesktopAssignmentType": { + "value": "Automatic" + }, + "maxSessionLimit": { + "value": 99999 + }, + "loadBalancerType": { + "value": "BreadthFirst" + }, + "customRdpProperty": { + "value": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;" + }, + "vmTemplate": { + "value": { + "domain": "domainname.onmicrosoft.com", + "galleryImageOffer": "office-365", + "galleryImagePublisher": "microsoftwindowsdesktop", + "galleryImageSKU": "20h1-evd-o365pp", + "imageType": "Gallery", + "imageUri": null, + "customImageId": null, + "namePrefix": "avdv2", + "osDiskType": "StandardSSD_LRS", + "useManagedDisks": true, + "vmSize": { + "id": "Standard_D2s_v3", + "cores": 2, + "ram": 8 + } + } + }, + "validationEnviroment": { + "value": false + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep new file mode 100644 index 000000000..2dbf23739 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep @@ -0,0 +1,204 @@ +@description('Required. Name of the Host Pool') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The friendly name of the Host Pool to be created.') +param hostpoolFriendlyName string = '' + +@description('Optional. The description of the Host Pool to be created.') +param hostpoolDescription string = '' + +@description('Optional. Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled.') +@allowed([ + 'Personal' + 'Pooled' +]) +param hostpoolType string = 'Pooled' + +@description('Optional. Set the type of assignment for a Personal Host Pool type') +@allowed([ + 'Automatic' + 'Direct' + '' +]) +param personalDesktopAssignmentType string = '' + +@description('Optional. Type of load balancer algorithm.') +@allowed([ + 'BreadthFirst' + 'DepthFirst' + 'Persistent' +]) +param loadBalancerType string = 'BreadthFirst' + +@description('Optional. Maximum number of sessions.') +param maxSessionLimit int = 99999 + +@description('Optional. Host Pool RDP properties') +param customRdpProperty string = 'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;' + +@description('Optional. Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation \'ring\' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment.') +param validationEnviroment bool = false + +@description('Optional. The necessary information for adding more VMs to this Host Pool.') +param vmTemplate object = {} + +@description('Optional. Host Pool token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the token will be valid for 8 hours.') +param tokenValidityLength string = 'PT8H' + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The type of preferred application group type, default to Desktop Application Group') +@allowed([ + 'Desktop' + 'None' + 'RailApplications' +]) +param preferredAppGroupType string = 'Desktop' + +@description('Optional. Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs.') +param startVMOnConnect bool = false + +@description('Optional. Validation host pool allows you to test service changes before they are deployed to production.') +param validationEnvironment bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' + 'Connection' + 'HostRegistration' + 'AgentHealthStatus' +]) +param logsToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' + 'Connection' + 'HostRegistration' + 'AgentHealthStatus' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var tokenExpirationTime = dateTimeAdd(baseTime, tokenValidityLength) + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-01-14-preview' = { + name: name + location: location + tags: tags + properties: { + friendlyName: hostpoolFriendlyName + description: hostpoolDescription + hostPoolType: hostpoolType + customRdpProperty: customRdpProperty + personalDesktopAssignmentType: any(personalDesktopAssignmentType) + preferredAppGroupType: preferredAppGroupType + maxSessionLimit: maxSessionLimit + loadBalancerType: loadBalancerType + validationEnviroment: validationEnviroment + startVMOnConnect: startVMOnConnect + validationEnvironment: validationEnvironment + registrationInfo: { + expirationTime: tokenExpirationTime + token: null + registrationTokenOperation: 'Update' + } + vmTemplate: ((!empty(vmTemplate)) ? null : string(vmTemplate)) + } +} + +resource hostPool_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${hostPool.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: hostPool +} + +resource hostPool_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${hostPool.name}-diagnosticsetting' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: hostPool +} + +module hostPool_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-HostPool-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: hostPool.id + } +}] + +@description('The resource ID of the AVD host pool') +output resourceId string = hostPool.id + +@description('The resource group the AVD host pool was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD host pool') +output name string = hostPool.name + +output hostPoolRestrationInfo object = hostPool.properties.registrationInfo + +@description('The expiration time for the registration token') +output tokenExpirationTime string = dateTimeAdd(baseTime, tokenValidityLength) diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/readme.md b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/readme.md new file mode 100644 index 000000000..1f33c2530 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/readme.md @@ -0,0 +1,132 @@ +# AVD Host Pools `[Microsoft.DesktopVirtualization/hostpools]` + +This module deploys an Azure virtual desktop host pool. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/hostPools` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a registration token. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customRdpProperty` | string | `audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;` | | Optional. Host Pool RDP properties | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `hostpoolDescription` | string | | | Optional. The description of the Host Pool to be created. | +| `hostpoolFriendlyName` | string | | | Optional. The friendly name of the Host Pool to be created. | +| `hostpoolType` | string | `Pooled` | `[Personal, Pooled]` | Optional. Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled. | +| `loadBalancerType` | string | `BreadthFirst` | `[BreadthFirst, DepthFirst, Persistent]` | Optional. Type of load balancer algorithm. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[Checkpoint, Error, Management, Connection, HostRegistration, AgentHealthStatus]` | `[Checkpoint, Error, Management, Connection, HostRegistration, AgentHealthStatus]` | Optional. The name of logs that will be streamed. | +| `maxSessionLimit` | int | `99999` | | Optional. Maximum number of sessions. | +| `name` | string | | | Required. Name of the Host Pool | +| `personalDesktopAssignmentType` | string | | `[Automatic, Direct, ]` | Optional. Set the type of assignment for a Personal Host Pool type | +| `preferredAppGroupType` | string | `Desktop` | `[Desktop, None, RailApplications]` | Optional. The type of preferred application group type, default to Desktop Application Group | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `startVMOnConnect` | bool | | | Optional. Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `tokenValidityLength` | string | `PT8H` | | Optional. Host Pool token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the token will be valid for 8 hours. | +| `validationEnviroment` | bool | | | Optional. Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation 'ring' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment. | +| `validationEnvironment` | bool | | | Optional. Validation host pool allows you to test service changes before they are deployed to production. | +| `vmTemplate` | object | `{object}` | | Optional. The necessary information for adding more VMs to this Host Pool. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `vmTemplate` + +The below parameter object is converted to an in-line string when handed over to the resource deployment, since that only takes strings. + +```json +"vmTemplate": { + "value": { + "domain": ".com", + "galleryImageOffer": "office-365", + "galleryImagePublisher": "microsoftwindowsdesktop", + "galleryImageSKU": "19h2-evd-o365pp", + "imageType": "Gallery", + "imageUri": null, + "customImageId": null, + "namePrefix": "AVDv2", + "osDiskType": "StandardSSD_LRS", + "useManagedDisks": true, + "vmSize": { + "id": "Standard_D2s_v3", + "cores": 2, + "ram": 8 + } + } +} +``` + +### Parameter Usage: `customRdpProperty` + +```json +"customRdpProperty": { + "value": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode ID:i:2;" +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD host pool | +| `resourceGroupName` | string | The resource group the AVD host pool was deployed into | +| `resourceId` | string | The resource ID of the AVD host pool | +| `tokenExpirationTime` | string | The expiration time for the registration token | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Hostpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/hostPools) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/version.json b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/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/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c91e776c6 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,37 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b') + 'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.DesktopVirtualization/workspaces@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: workspace +}] diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..7220e4d78 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdws-x-001" + }, + "location": { + "value": "westeurope" + }, + "appGroupResourceIds": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.DesktopVirtualization/applicationgroups/adp-<>-az-avdag-x-001" + ] + }, + "workspaceFriendlyName": { + "value": "My first AVD Workspace" + }, + "workspaceDescription": { + "value": "This is my first AVD Workspace" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep new file mode 100644 index 000000000..9f153bdef --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep @@ -0,0 +1,126 @@ +@description('Required. The name of the workspace to be attach to new Application Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Resource IDs fo the existing Application groups this workspace will group together.') +param appGroupResourceIds array = [] + +@description('Optional. The friendly name of the Workspace to be created.') +param workspaceFriendlyName string = '' + +@description('Optional. The description of the Workspace to be created.') +param workspaceDescription string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' + 'Feed' +]) +param logsToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' + 'Feed' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource workspace 'Microsoft.DesktopVirtualization/workspaces@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + applicationGroupReferences: appGroupResourceIds + description: workspaceDescription + friendlyName: workspaceFriendlyName + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${workspace.name}-diagnosticsetting' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Workspace-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The resource ID of the AVD workspace') +output resourceId string = workspace.id + +@description('The resource group the AVD workspace was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD workspace') +output name string = workspace.name diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/readme.md b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/readme.md new file mode 100644 index 000000000..3231c5e64 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/readme.md @@ -0,0 +1,87 @@ +# AVD Workspaces `[Microsoft.DesktopVirtualization/workspaces]` + +This module deploys an Azure virtual desktop workspace. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/workspaces` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appGroupResourceIds` | array | `[]` | | Required. Resource IDs fo the existing Application groups this workspace will group together. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[Checkpoint, Error, Management, Feed]` | `[Checkpoint, Error, Management, Feed]` | Optional. The name of logs that will be streamed. | +| `name` | string | | | Required. The name of the workspace to be attach to new Application Group. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `workspaceDescription` | string | | | Optional. The description of the Workspace to be created. | +| `workspaceFriendlyName` | string | | | Optional. The friendly name of the Workspace to be created. | + + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD workspace | +| `resourceGroupName` | string | The resource group the AVD workspace was deployed into | +| `resourceId` | string | The resource ID of the AVD workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/workspaces) diff --git a/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/version.json b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/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/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..36b073bf9 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Cosmos DB Account Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'CosmosBackupOperator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-06-15' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(databaseAccount.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: databaseAccount +}] diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/deploy.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/deploy.bicep new file mode 100644 index 000000000..d552dcc6f --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/deploy.bicep @@ -0,0 +1,268 @@ +@description('Required. Name of the Database Account') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Database Account resource.') +param tags object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The offer type for the Cosmos DB database account.') +@allowed([ + 'Standard' +]) +param databaseAccountOfferType string = 'Standard' + +@description('Required. Locations enabled for the Cosmos DB account.') +param locations array + +@allowed([ + 'Eventual' + 'ConsistentPrefix' + 'Session' + 'BoundedStaleness' + 'Strong' +]) +@description('Optional. The default consistency level of the Cosmos DB account.') +param defaultConsistencyLevel string = 'Session' + +@description('Optional. Enable automatic failover for regions') +param automaticFailover bool = true + +@minValue(10) +@maxValue(2147483647) +@description('Optional. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000.') +param maxStalenessPrefix int = 100000 + +@minValue(5) +@maxValue(86400) +@description('Optional. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400.') +param maxIntervalInSeconds int = 300 + +@description('Optional. Specifies the MongoDB server version to use.') +@allowed([ + '3.2' + '3.6' + '4.0' +]) +param serverVersion string = '4.0' + +@description('Optional. SQL Databases configurations') +param sqlDatabases array = [] + +@description('Optional. MongoDB Databases configurations') +param mongodbDatabases array = [] + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DataPlaneRequests' + 'MongoRequests' + 'QueryRuntimeStatistics' + 'PartitionKeyStatistics' + 'PartitionKeyRUConsumption' + 'ControlPlaneRequests' + 'CassandraRequests' + 'GremlinRequests' + 'TableApiRequests' +]) +param logsToEnable array = [ + 'DataPlaneRequests' + 'MongoRequests' + 'QueryRuntimeStatistics' + 'PartitionKeyStatistics' + 'PartitionKeyRUConsumption' + 'ControlPlaneRequests' + 'CassandraRequests' + 'GremlinRequests' + 'TableApiRequests' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Requests' +]) +param metricsToEnable array = [ + 'Requests' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var consistencyPolicy = { + Eventual: { + defaultConsistencyLevel: 'Eventual' + } + ConsistentPrefix: { + defaultConsistencyLevel: 'ConsistentPrefix' + } + Session: { + defaultConsistencyLevel: 'Session' + } + BoundedStaleness: { + defaultConsistencyLevel: 'BoundedStaleness' + maxStalenessPrefix: maxStalenessPrefix + maxIntervalInSeconds: maxIntervalInSeconds + } + Strong: { + defaultConsistencyLevel: 'Strong' + } +} + +var databaseAccount_locations = [for location in locations: { + failoverPriority: location.failoverPriority + isZoneRedundant: location.isZoneRedundant + locationName: location.locationName +}] + +var kind = !empty(sqlDatabases) ? 'GlobalDocumentDB' : (!empty(mongodbDatabases) ? 'MongoDB' : 'Parse') + +var databaseAccount_properties = !empty(sqlDatabases) ? { + consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] + locations: databaseAccount_locations + databaseAccountOfferType: databaseAccountOfferType + enableAutomaticFailover: automaticFailover +} : (!empty(mongodbDatabases) ? { + consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] + locations: databaseAccount_locations + databaseAccountOfferType: databaseAccountOfferType + apiProperties: { + serverVersion: serverVersion + } +} : { + databaseAccountOfferType: databaseAccountOfferType +}) + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-06-15' = { + name: name + location: location + tags: tags + identity: identity + kind: kind + properties: databaseAccount_properties +} + +resource databaseAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${databaseAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: databaseAccount +} + +resource databaseAccount_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${databaseAccount.name}-diagnosticsetting' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: databaseAccount +} + +module databaseAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: databaseAccount.id + } +}] + +module sqlDatabases_resource 'sqlDatabases/deploy.bicep' = [for sqlDatabase in sqlDatabases: { + name: '${uniqueString(deployment().name, location)}-sqldb-${sqlDatabase.name}' + params: { + databaseAccountName: databaseAccount.name + name: sqlDatabase.name + containers: contains(sqlDatabase, 'containers') ? sqlDatabase.containers : [] + } +}] + +module mongodbDatabases_resource 'mongodbDatabases/deploy.bicep' = [for mongodbDatabase in mongodbDatabases: { + name: '${uniqueString(deployment().name, location)}-mongodb-${mongodbDatabase.name}' + params: { + databaseAccountName: databaseAccount.name + name: mongodbDatabase.name + collections: contains(mongodbDatabase, 'collections') ? mongodbDatabase.collections : [] + } +}] + +@description('The name of the database account.') +output name string = databaseAccount.name + +@description('The resource ID of the database account.') +output resourceId string = databaseAccount.id + +@description('The name of the resource group the database account was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(databaseAccount.identity, 'principalId') ? databaseAccount.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/deploy.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/deploy.bicep new file mode 100644 index 000000000..20c9696c8 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/deploy.bicep @@ -0,0 +1,57 @@ +@description('Required. Name of the Cosmos DB database account.') +param databaseAccountName string + +@description('Required. Name of the mongodb database') +param mongodbDatabaseName string + +@description('Required. Name of the collection') +param name string + +@description('Optional. Name of the mongodb database') +param throughput int = 400 + +@description('Required. Indexes for the collection') +param indexes array + +@description('Required. ShardKey for the collection') +param shardKey object + +@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 databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName + + resource mongodbDatabase 'mongodbDatabases@2021-07-01-preview' existing = { + name: mongodbDatabaseName + } +} + +resource collection 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections@2021-07-01-preview' = { + name: name + parent: databaseAccount::mongodbDatabase + properties: { + options: { + throughput: throughput + } + resource: { + id: name + indexes: indexes + shardKey: shardKey + } + } +} + +@description('The name of the mongodb database.') +output name string = collection.name + +@description('The resource ID of the mongodb database.') +output resourceId string = collection.id + +@description('The name of the resource group the mongodb database was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/readme.md b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/readme.md new file mode 100644 index 000000000..2bd2c4a27 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/readme.md @@ -0,0 +1,91 @@ +# DocumentDB Database Account MongoDB databases Collections `[Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections]` + +This module deploys a collection within a MongoDB. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections` | 2021-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 | +| `databaseAccountName` | string | | | Required. Name of the Cosmos DB database account. | +| `indexes` | array | | | Required. Indexes for the collection | +| `mongodbDatabaseName` | string | | | Required. Name of the mongodb database | +| `name` | string | | | Required. Name of the collection | +| `shardKey` | object | | | Required. ShardKey for the collection | +| `throughput` | int | `400` | | Optional. Name of the mongodb database | + +### Parameter Usage: `indexes` + +Array of index keys as MongoIndex. The array contains keys for each MongoDB collection in the Azure Cosmos DB service with a collection resource object (as `key`) and collection index options (as `options`). + +```json + "indexes": { + "value": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "estate_id", + "estate_address" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ] + } +``` + +### Parameter Usage: `shardKey` + +The shard key and partition kind pair, only support "Hash" partition kind. + +```json + "shardKey": { + "value": { + "estate_id": "Hash" + } + } +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the mongodb database. | +| `resourceGroupName` | string | The name of the resource group the mongodb database was created in. | +| `resourceId` | string | The resource ID of the mongodb database. | + +## Template references + +- [Databaseaccounts/Mongodbdatabases/Collections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases/collections) diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/version.json b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/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/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/deploy.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/deploy.bicep new file mode 100644 index 000000000..6324c00cd --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/deploy.bicep @@ -0,0 +1,60 @@ +@description('Required. Name of the Cosmos DB database account.') +param databaseAccountName string + +@description('Required. Name of the mongodb database') +param name string + +@description('Optional. Name of the mongodb database') +param throughput int = 400 + +@description('Optional. Collections in the mongodb database') +param collections array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName +} + +resource mongodbDatabase 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases@2021-07-01-preview' = { + name: name + parent: databaseAccount + tags: tags + properties: { + resource: { + id: name + } + options: { + throughput: throughput + } + } +} + +module mongodbDatabase_collections 'collections/deploy.bicep' = [for collection in collections: { + name: '${uniqueString(deployment().name, mongodbDatabase.name)}-collection-${collection.name}' + params: { + databaseAccountName: databaseAccountName + mongodbDatabaseName: name + name: collection.name + indexes: collection.indexes + shardKey: collection.shardKey + } +}] + +@description('The name of the mongodb database.') +output name string = mongodbDatabase.name + +@description('The resource ID of the mongodb database.') +output resourceId string = mongodbDatabase.id + +@description('The name of the resource group the mongodb database was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/readme.md b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/readme.md new file mode 100644 index 000000000..add1e582c --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/readme.md @@ -0,0 +1,55 @@ +# DocumentDB Database Account MongoDB databases `[Microsoft.DocumentDB/databaseAccounts/mongodbDatabases]` + +This module deploys a MongoDB within a CosmosDB account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases` | 2021-07-01-preview | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections` | 2021-07-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `collections` | _[collections](collections/readme.md)_ array | `[]` | | Optional. Collections in the mongodb database | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `databaseAccountName` | string | | | Required. Name of the Cosmos DB database account. | +| `name` | string | | | Required. Name of the mongodb database | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `throughput` | int | `400` | | Optional. Name of the mongodb database | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `collections` + +Please reference the documentation for [collections](./collections/readme.md) + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the mongodb database. | +| `resourceGroupName` | string | The name of the resource group the mongodb database was created in. | +| `resourceId` | string | The resource ID of the mongodb database. | + +## Template references + +- [Databaseaccounts/Mongodbdatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases) +- [Databaseaccounts/Mongodbdatabases/Collections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases/collections) diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/version.json b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/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/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/readme.md b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/readme.md new file mode 100644 index 000000000..85029f7ee --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/readme.md @@ -0,0 +1,220 @@ +# DocumentDB Database Accounts `[Microsoft.DocumentDB/databaseAccounts]` + +This module deploys a DocumentDB database account and its child resources. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DocumentDB/databaseAccounts` | 2021-06-15 | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases` | 2021-07-01-preview | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections` | 2021-07-01-preview | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases` | 2021-06-15 | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | 2021-07-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automaticFailover` | bool | `True` | | Optional. Enable automatic failover for regions | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `databaseAccountOfferType` | string | `Standard` | `[Standard]` | Optional. The offer type for the Cosmos DB database account. | +| `defaultConsistencyLevel` | string | `Session` | `[Eventual, ConsistentPrefix, Session, BoundedStaleness, Strong]` | Optional. The default consistency level of the Cosmos DB account. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `locations` | array | | | Required. Locations enabled for the Cosmos DB account. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[DataPlaneRequests, MongoRequests, QueryRuntimeStatistics, PartitionKeyStatistics, PartitionKeyRUConsumption, ControlPlaneRequests, CassandraRequests, GremlinRequests, TableApiRequests]` | `[DataPlaneRequests, MongoRequests, QueryRuntimeStatistics, PartitionKeyStatistics, PartitionKeyRUConsumption, ControlPlaneRequests, CassandraRequests, GremlinRequests, TableApiRequests]` | Optional. The name of logs that will be streamed. | +| `maxIntervalInSeconds` | int | `300` | | Optional. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400. | +| `maxStalenessPrefix` | int | `100000` | | Optional. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000. | +| `metricsToEnable` | array | `[Requests]` | `[Requests]` | Optional. The name of metrics that will be streamed. | +| `mongodbDatabases` | _[mongodbDatabases](mongodbDatabases/readme.md)_ array | `[]` | | Optional. MongoDB Databases configurations | +| `name` | string | | | Required. Name of the Database Account | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serverVersion` | string | `4.0` | `[3.2, 3.6, 4.0]` | Optional. Specifies the MongoDB server version to use. | +| `sqlDatabases` | _[sqlDatabases](sqlDatabases/readme.md)_ array | `[]` | | Optional. SQL Databases configurations | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the Database Account resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `locations` + +```json +"locations": { + "value": [ + { + "failoverPriority": 1, + "locationName": "East US", + "isZoneRedundant": false + } + ] +} +``` + +### Parameter Usage: `sqlDatabases` + +```json +"sqlDatabases": { + "value": [ + { + "name": "sxx-az-sql-x-001", + "containers": [ + "container-001", + "container-002" + ] + }, + { + "name": "sxx-az-sql-x-002", + "containers": [] + } + ] +} +``` + +### Parameter Usage: `mongodbDatabases` + +```json +"mongodbDatabases": { + "value": [ + { + "name": "sxx-az-mdb-x-001", + "collections": [ + <...> + ] + }, + { + "name": "sxx-az-mdb-x-002", + "collections": [ + <...> + ] + } + ] +} +``` + +Please reference the documentation for [mongodbDatabases](./mongodbDatabases/readme.md) + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Desktop Virtualization User", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the database account. | +| `resourceGroupName` | string | The name of the resource group the database account was created in. | +| `resourceId` | string | The resource ID of the database account. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Databaseaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-06-15/databaseAccounts) +- [Databaseaccounts/Mongodbdatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases) +- [Databaseaccounts/Mongodbdatabases/Collections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases/collections) +- [Databaseaccounts/Sqldatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-06-15/databaseAccounts/sqlDatabases) +- [Databaseaccounts/Sqldatabases/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/sqlDatabases/containers) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/deploy.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/deploy.bicep new file mode 100644 index 000000000..ed9016c51 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/deploy.bicep @@ -0,0 +1,68 @@ +@description('Required. Name of the Database Account') +param databaseAccountName string + +@description('Required. Name of the SQL Database ') +param sqlDatabaseName string + +@description('Required. Name of the container.') +param name string + +@description('Optional. Request Units per second') +param throughput int = 400 + +@description('Optional. Tags of the SQL Database resource.') +param tags object = {} + +@description('Optional. List of paths using which data within the container can be partitioned') +param paths array = [] + +@description('Optional. Indicates the kind of algorithm used for partitioning') +@allowed([ + 'Hash' + 'MultiHash' + 'Range' +]) +param kind string = 'Hash' + +@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 databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName + + resource sqlDatabase 'sqlDatabases@2021-07-01-preview' existing = { + name: sqlDatabaseName + } +} + +resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2021-07-01-preview' = { + name: name + parent: databaseAccount::sqlDatabase + tags: tags + properties: { + resource: { + id: name + partitionKey: { + paths: paths + kind: kind + } + } + options: { + throughput: throughput + } + } +} + +@description('The name of the container.') +output name string = container.name + +@description('The resource ID of the container.') +output resourceId string = container.id + +@description('The name of the resource group the container was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readme.md b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readme.md new file mode 100644 index 000000000..766b01cee --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readme.md @@ -0,0 +1,49 @@ +# DocumentDB Database Account SQL Databases Containers `[Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers]` + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | 2021-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 | +| `databaseAccountName` | string | | | Required. Name of the Database Account | +| `kind` | string | `Hash` | `[Hash, MultiHash, Range]` | Optional. Indicates the kind of algorithm used for partitioning | +| `name` | string | | | Required. Name of the container. | +| `paths` | array | `[]` | | Optional. List of paths using which data within the container can be partitioned | +| `sqlDatabaseName` | string | | | Required. Name of the SQL Database | +| `tags` | object | `{object}` | | Optional. Tags of the SQL Database resource. | +| `throughput` | int | `400` | | Optional. Request Units per second | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the container. | +| `resourceGroupName` | string | The name of the resource group the container was created in. | +| `resourceId` | string | The resource ID of the container. | + +## Template references + +- [Databaseaccounts/Sqldatabases/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/sqlDatabases/containers) diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/version.json b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/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/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/deploy.bicep b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/deploy.bicep new file mode 100644 index 000000000..3f8fb488e --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/deploy.bicep @@ -0,0 +1,60 @@ +@description('Required. ID of the Cosmos DB database account.') +param databaseAccountName string + +@description('Required. Name of the SQL database ') +param name string + +@description('Optional. Array of containers to deploy in the SQL database.') +param containers array = [] + +@description('Optional. Request units per second') +param throughput int = 400 + +@description('Optional. Tags of the SQL database resource.') +param tags object = {} + +@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 databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName +} + +resource sqlDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2021-06-15' = { + name: name + parent: databaseAccount + tags: tags + properties: { + resource: { + id: name + } + options: { + throughput: throughput + } + } +} + +module container 'containers/deploy.bicep' = [for container in containers: { + name: '${uniqueString(deployment().name, sqlDatabase.name)}-sqldb-${container.name}' + params: { + databaseAccountName: databaseAccountName + sqlDatabaseName: name + name: container.name + paths: container.paths + kind: container.kind + } +}] + +@description('The name of the SQL database.') +output name string = sqlDatabase.name + +@description('The resource ID of the SQL database.') +output resourceId string = sqlDatabase.id + +@description('The name of the resource group the SQL database was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/readme.md b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/readme.md new file mode 100644 index 000000000..1812f895f --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/readme.md @@ -0,0 +1,49 @@ +# DocumentDB Database Account SQL Databases `[Microsoft.DocumentDB/databaseAccounts/sqlDatabases]` + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases` | 2021-06-15 | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | 2021-07-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `containers` | _[containers](containers/readme.md)_ array | `[]` | | Optional. Array of containers to deploy in the SQL database. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `databaseAccountName` | string | | | Required. ID of the Cosmos DB database account. | +| `name` | string | | | Required. Name of the SQL database | +| `tags` | object | `{object}` | | Optional. Tags of the SQL database resource. | +| `throughput` | int | `400` | | Optional. Request units per second | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SQL database. | +| `resourceGroupName` | string | The name of the resource group the SQL database was created in. | +| `resourceId` | string | The resource ID of the SQL database. | + +## Template references + +- [Databaseaccounts/Sqldatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-06-15/databaseAccounts/sqlDatabases) +- [Databaseaccounts/Sqldatabases/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/sqlDatabases/containers) diff --git a/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/version.json b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/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/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/version.json b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.DocumentDB/databaseAccounts/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/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..82ab478cd --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..af15c17cd --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(systemTopic.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: systemTopic +}] diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json new file mode 100644 index 000000000..87be2f37f --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.parameters/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": { + "name": { + "value": "<>-az-egstn-x-002" + }, + "source": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "topicType": { + "value": "Microsoft.Storage.StorageAccounts" + } + } +} diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/.parameters/parameters.json b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.parameters/parameters.json new file mode 100644 index 000000000..46728a692 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-egstn-x-001" + }, + "source": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "topicType": { + "value": "Microsoft.Storage.StorageAccounts" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/deploy.bicep b/carml/1.0.0/Microsoft.EventGrid/systemTopics/deploy.bicep new file mode 100644 index 000000000..53996c3bf --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/deploy.bicep @@ -0,0 +1,165 @@ +@description('Required. The name of the Event Grid Topic') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Required. Source for the system topic.') +param source string + +@description('Required. TopicType for the system topic.') +param topicType string + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DeliveryFailures' +]) +param logsToEnable array = [ + 'DeliveryFailures' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' = { + name: name + location: location + identity: identity + tags: tags + properties: { + source: source + topicType: topicType + } +} + +resource systemTopic_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${systemTopic.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: systemTopic +} + +resource systemTopic_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${systemTopic.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: systemTopic +} + +module systemTopic_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-EventGrid-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: systemTopic.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module systemTopic_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EventGrid-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: systemTopic.id + } +}] + +@description('The name of the event grid system topic') +output name string = systemTopic.name + +@description('The resource ID of the event grid system topic') +output resourceId string = systemTopic.id + +@description('The name of the resource group the event grid system topic was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(systemTopic.identity, 'principalId') ? systemTopic.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/readme.md b/carml/1.0.0/Microsoft.EventGrid/systemTopics/readme.md new file mode 100644 index 000000000..6a42a7441 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/readme.md @@ -0,0 +1,143 @@ +# Event Grid Topics `[Microsoft.EventGrid/systemTopics]` + +This module deploys an event grid topic. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventGrid/systemTopics` | 2021-12-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[DeliveryFailures]` | `[DeliveryFailures]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the Event Grid Topic | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `source` | string | | | Required. Source for the system topic. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `topicType` | string | | | Required. TopicType for the system topic. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the event grid system topic | +| `resourceGroupName` | string | The name of the resource group the event grid system topic was deployed into | +| `resourceId` | string | The resource ID of the event grid system topic | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Systemtopics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2021-12-01/systemTopics) diff --git a/carml/1.0.0/Microsoft.EventGrid/systemTopics/version.json b/carml/1.0.0/Microsoft.EventGrid/systemTopics/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/systemTopics/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/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..82ab478cd --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..59b68eba6 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource eventGrid 'Microsoft.EventGrid/topics@2020-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(eventGrid.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: eventGrid +}] diff --git a/carml/1.0.0/Microsoft.EventGrid/topics/.parameters/parameters.json b/carml/1.0.0/Microsoft.EventGrid/topics/.parameters/parameters.json new file mode 100644 index 000000000..6a793c3a9 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-egtn-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.EventGrid/topics/deploy.bicep b/carml/1.0.0/Microsoft.EventGrid/topics/deploy.bicep new file mode 100644 index 000000000..5b9a81182 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/deploy.bicep @@ -0,0 +1,150 @@ +@description('Required. The name of the Event Grid Topic') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Determines if traffic is allowed over public network.') +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Array of IPs to whitelist.') +param inboundIpRules array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DeliveryFailures' + 'PublishFailures' +]) +param logsToEnable array = [ + 'DeliveryFailures' + 'PublishFailures' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource eventGrid 'Microsoft.EventGrid/topics@2020-06-01' = { + name: name + location: location + tags: tags + properties: { + publicNetworkAccess: publicNetworkAccess + inboundIpRules: (empty(inboundIpRules) ? null : inboundIpRules) + } +} + +resource eventGrid_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${eventGrid.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: eventGrid +} + +resource eventGrid_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${eventGrid.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: eventGrid +} + +module eventGrid_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-EventGrid-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: eventGrid.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module eventGrid_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EventGrid-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: eventGrid.id + } +}] + +@description('The name of the event grid topic') +output name string = eventGrid.name + +@description('The resource ID of the event grid') +output resourceId string = eventGrid.id + +@description('The name of the resource group the event grid was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.EventGrid/topics/readme.md b/carml/1.0.0/Microsoft.EventGrid/topics/readme.md new file mode 100644 index 000000000..a05d651eb --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/readme.md @@ -0,0 +1,127 @@ +# Event Grid Topics `[Microsoft.EventGrid/topics]` + +This module deploys an event grid topic. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventGrid/topics` | 2020-06-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `inboundIpRules` | array | `[]` | | Optional. Array of IPs to whitelist. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[DeliveryFailures, PublishFailures]` | `[DeliveryFailures, PublishFailures]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the Event Grid Topic | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `publicNetworkAccess` | string | `Enabled` | | Optional. Determines if traffic is allowed over public network. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the event grid topic | +| `resourceGroupName` | string | The name of the resource group the event grid was deployed into | +| `resourceId` | string | The resource ID of the event grid | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Topics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2020-06-01/topics) diff --git a/carml/1.0.0/Microsoft.EventGrid/topics/version.json b/carml/1.0.0/Microsoft.EventGrid/topics/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventGrid/topics/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/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..ac35d182f --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (!empty(privateEndpointObj.customDnsConfigs) ? privateEndpointObj.customDnsConfigs : null) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..21a191922 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/.bicep/nested_rbac.bicep @@ -0,0 +1,37 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Schema Registry Contributor (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5dffeca3-4936-4216-b2bc-10343a5abb25') + 'Schema Registry Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2c56ea50-c6b3-40a6-83c0-9d98858bc7d2') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2017-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(eventHubNamespace.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: eventHubNamespace +}] diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.EventHub/namespaces/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/.parameters/parameters.json b/carml/1.0.0/Microsoft.EventHub/namespaces/.parameters/parameters.json new file mode 100644 index 000000000..03dace80b --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/.parameters/parameters.json @@ -0,0 +1,111 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-evnsp-x-001" + }, + "authorizationRules": { + "value": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "SendListenAccess", + "rights": [ + "Listen", + "Send" + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "eventHubs": { + "value": [ + { + "name": "<>-az-evh-x-001", + "authorizationRules": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "SendListenAccess", + "rights": [ + "Listen", + "Send" + ] + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "messageRetentionInDays": 1, + "partitionCount": 2, + "status": "Active", + "captureDescriptionEnabled": true, + "captureDescriptionEncoding": "Avro", + "captureDescriptionIntervalInSeconds": 300, + "captureDescriptionSizeLimitInBytes": 314572800, + "captureDescriptionDestinationName": "EventHubArchive.AzureBlockBlob", + "captureDescriptionDestinationStorageAccountResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "captureDescriptionDestinationBlobContainer": "eventhub", + "captureDescriptionDestinationArchiveNameFormat": "{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}", + "captureDescriptionSkipEmptyArchives": true, + "consumerGroups": [ + { + "name": "custom", + "userMetadata": "customMetadata" + } + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/deploy.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/deploy.bicep new file mode 100644 index 000000000..c020ab271 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/deploy.bicep @@ -0,0 +1,42 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the authorization rule') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@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 namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource authorizationRule 'Microsoft.EventHub/namespaces/AuthorizationRules@2017-04-01' = { + name: name + parent: namespace + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the resource group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/readme.md b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/readme.md new file mode 100644 index 000000000..fd85ebfbe --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/readme.md @@ -0,0 +1,30 @@ +# EventHub Namespace Authorization Rule `[Microsoft.EventHub/namespaces/authorizationRules]` + +This module deploys an EventHub Namespace Authorization Rule + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/authorizationRules` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. The name of the authorization rule | +| `namespaceName` | string | | | Required. The name of the event hub namespace | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | Optional. The rights associated with the rule. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the resource group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/authorizationRules) diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/version.json b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/authorizationRules/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/carml/1.0.0/Microsoft.EventHub/namespaces/deploy.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/deploy.bicep new file mode 100644 index 000000000..e46a037f4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/deploy.bicep @@ -0,0 +1,297 @@ +@description('Optional. The name of the event hub namespace. If no name is provided, then unique name will be created.') +@maxLength(50) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. event hub plan SKU name') +@allowed([ + 'Basic' + 'Standard' +]) +param skuName string = 'Standard' + +@description('Optional. Event Hub plan scale-out capacity of the resource') +@minValue(1) +@maxValue(20) +param skuCapacity int = 1 + +@description('Optional. Switch to make the Event Hub Namespace zone redundant.') +param zoneRedundant bool = false + +@description('Optional. Switch to enable the Auto Inflate feature of Event Hub.') +param isAutoInflateEnabled bool = false + +@description('Optional. Upper limit of throughput units when AutoInflate is enabled, value should be within 0 to 20 throughput units.') +@minValue(0) +@maxValue(20) +param maximumThroughputUnits int = 1 + +@description('Optional. Authorization Rules for the Event Hub namespace') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. Configuration Details for private endpoints.For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints array = [] + +@description('Optional. Service endpoint object information') +param networkAcls object = {} + +@description('Optional. Virtual Network ID to lock down the Event Hub.') +param vNetId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The event hubs to deploy into this namespace') +param eventHubs array = [] + +@description('Optional. The disaster recovery config for this namespace') +param disasterRecoveryConfig object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ArchiveLogs' + 'OperationalLogs' + 'KafkaCoordinatorLogs' + 'KafkaUserErrorLogs' + 'EventHubVNetConnectionEvent' + 'CustomerManagedKeyUserLogs' + 'AutoScaleLogs' +]) +param logsToEnable array = [ + 'ArchiveLogs' + 'OperationalLogs' + 'KafkaCoordinatorLogs' + 'KafkaUserErrorLogs' + 'EventHubVNetConnectionEvent' + 'CustomerManagedKeyUserLogs' + 'AutoScaleLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var maxNameLength = 50 +var uniqueEventHubNamespaceUntrim = uniqueString('EventHub Namespace${baseTime}') +var uniqueEventHubNamespace = length(uniqueEventHubNamespaceUntrim) > maxNameLength ? substring(uniqueEventHubNamespaceUntrim, 0, maxNameLength) : uniqueEventHubNamespaceUntrim +var name_var = empty(name) ? uniqueEventHubNamespace : name +var maximumThroughputUnits_var = !isAutoInflateEnabled ? 0 : maximumThroughputUnits +var virtualNetworkRules = [for index in range(0, (empty(networkAcls) ? 0 : length(networkAcls.virtualNetworkRules))): { + id: '${vNetId}/subnets/${networkAcls.virtualNetworkRules[index].subnet}' +}] +var networkAcls_var = { + bypass: !empty(networkAcls) ? networkAcls.bypass : null + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: !empty(networkAcls) ? virtualNetworkRules : null + ipRules: !empty(networkAcls) ? (length(networkAcls.ipRules) > 0 ? networkAcls.ipRules : null) : null +} + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' = { + name: name_var + location: location + tags: tags + identity: identity + sku: { + name: skuName + tier: skuName + capacity: skuCapacity + } + properties: { + zoneRedundant: zoneRedundant + isAutoInflateEnabled: isAutoInflateEnabled + maximumThroughputUnits: maximumThroughputUnits_var + networkAcls: !empty(networkAcls) ? networkAcls_var : null + } +} + +resource eventHubNamespace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${eventHubNamespace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: eventHubNamespace +} + +resource eventHubNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${eventHubNamespace.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: eventHubNamespace +} + +module eventHubNamespace_eventHubs 'eventhubs/deploy.bicep' = [for (eventHub, index) in eventHubs: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-EventHub-${index}' + params: { + namespaceName: eventHubNamespace.name + name: eventHub.name + authorizationRules: contains(eventHub, 'authorizationRules') ? eventHub.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + } + ] + captureDescriptionDestinationArchiveNameFormat: contains(eventHub, 'captureDescriptionDestinationArchiveNameFormat') ? eventHub.captureDescriptionDestinationArchiveNameFormat : '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + captureDescriptionDestinationBlobContainer: contains(eventHub, 'captureDescriptionDestinationBlobContainer') ? eventHub.captureDescriptionDestinationBlobContainer : '' + captureDescriptionDestinationName: contains(eventHub, 'captureDescriptionDestinationName') ? eventHub.captureDescriptionDestinationName : 'EventHubArchive.AzureBlockBlob' + captureDescriptionDestinationStorageAccountResourceId: contains(eventHub, 'captureDescriptionDestinationStorageAccountResourceId') ? eventHub.captureDescriptionDestinationStorageAccountResourceId : '' + captureDescriptionEnabled: contains(eventHub, 'captureDescriptionEnabled') ? eventHub.captureDescriptionEnabled : false + captureDescriptionEncoding: contains(eventHub, 'captureDescriptionEncoding') ? eventHub.captureDescriptionEncoding : 'Avro' + captureDescriptionIntervalInSeconds: contains(eventHub, 'captureDescriptionIntervalInSeconds') ? eventHub.captureDescriptionIntervalInSeconds : 300 + captureDescriptionSizeLimitInBytes: contains(eventHub, 'captureDescriptionSizeLimitInBytes') ? eventHub.captureDescriptionSizeLimitInBytes : 314572800 + captureDescriptionSkipEmptyArchives: contains(eventHub, 'captureDescriptionSkipEmptyArchives') ? eventHub.captureDescriptionSkipEmptyArchives : false + consumerGroups: contains(eventHub, 'consumerGroups') ? eventHub.consumerGroups : [] + lock: contains(eventHub, 'lock') ? eventHub.lock : 'NotSpecified' + messageRetentionInDays: contains(eventHub, 'messageRetentionInDays') ? eventHub.messageRetentionInDays : 1 + partitionCount: contains(eventHub, 'partitionCount') ? eventHub.partitionCount : 2 + roleAssignments: contains(eventHub, 'roleAssignments') ? eventHub.roleAssignments : [] + status: contains(eventHub, 'status') ? eventHub.status : 'Active' + } +}] + +module eventHubNamespace_diasterRecoveryConfig 'disasterRecoveryConfigs/deploy.bicep' = if (!empty(disasterRecoveryConfig)) { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-DisRecConfig' + params: { + namespaceName: eventHubNamespace.name + name: disasterRecoveryConfig.name + partnerNamespaceId: contains(disasterRecoveryConfig, 'partnerNamespaceId') ? disasterRecoveryConfig.partnerNamespaceId : '' + } +} + +module eventHubNamespace_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-AuthRule-${index}' + params: { + namespaceName: eventHubNamespace.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module eventHubNamespace_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: eventHubNamespace.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: endpoint + tags: tags + } +}] + +module eventHubNamespace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: eventHubNamespace.id + } +}] + +@description('The name of the eventspace.') +output name string = eventHubNamespace.name + +@description('The resource ID of the eventspace.') +output resourceId string = eventHubNamespace.id + +@description('The resource group where the namespace is deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(eventHubNamespace.identity, 'principalId') ? eventHubNamespace.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/deploy.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/deploy.bicep new file mode 100644 index 000000000..1cf2a6917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/deploy.bicep @@ -0,0 +1,37 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the disaster recovery config') +param name string + +@description('Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing') +param partnerNamespaceId string = '' + +@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 namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource disasterRecoveryConfig 'Microsoft.EventHub/namespaces/disasterRecoveryConfigs@2017-04-01' = { + name: name + parent: namespace + properties: { + partnerNamespace: partnerNamespaceId + } +} + +@description('The name of the disaster recovery config.') +output name string = disasterRecoveryConfig.name + +@description('The resource ID of the disaster recovery config.') +output resourceId string = disasterRecoveryConfig.id + +@description('The name of the resource group the disaster recovery config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/readme.md b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/readme.md new file mode 100644 index 000000000..da2b06997 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/readme.md @@ -0,0 +1,30 @@ +# EventHub Namespace Disaster Recovery Config `[Microsoft.EventHub/namespaces/disasterRecoveryConfigs]` + +This module deploys an EventHub Namespace Disaster Recovery Config + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/disasterRecoveryConfigs` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. The name of the disaster recovery config | +| `namespaceName` | string | | | Required. The name of the event hub namespace | +| `partnerNamespaceId` | string | | | Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disaster recovery config. | +| `resourceGroupName` | string | The name of the resource group the disaster recovery config was created in. | +| `resourceId` | string | The resource ID of the disaster recovery config. | + +## Template references + +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/disasterRecoveryConfigs) diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/version.json b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/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/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e9cc6a9f5 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(split(resourceId, '/')[0], split(resourceId, '/')[1], principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: eventHub +}] diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/deploy.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/deploy.bicep new file mode 100644 index 000000000..dfb7faa1c --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/deploy.bicep @@ -0,0 +1,49 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the event hub namespace event hub') +param eventHubName string + +@description('Required. The name of the authorization rule') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@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 namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource eventhub 'eventHubs@2021-06-01-preview' existing = { + name: eventHubName + } +} + +resource authorizationRule 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules@2021-06-01-preview' = { + name: name + parent: namespace::eventhub + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the resource group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/readme.md b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/readme.md new file mode 100644 index 000000000..aaa24b3bb --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/readme.md @@ -0,0 +1,31 @@ +# EventHub Namespace EventHubs Authorization Rule `[Microsoft.EventHub/namespaces/eventhubs/authorizationRules]` + +This module deploys an EventHub Namespace EventHubs Authorization Rule + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/eventhubs/authorizationRules` | 2021-06-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 | +| `eventHubName` | string | | | Required. The name of the event hub namespace event hub | +| `name` | string | | | Required. The name of the authorization rule | +| `namespaceName` | string | | | Required. The name of the event hub namespace | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | Optional. The rights associated with the rule. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the resource group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Eventhubs/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/authorizationRules) diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/version.json b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/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/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/deploy.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/deploy.bicep new file mode 100644 index 000000000..90d9958a2 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/deploy.bicep @@ -0,0 +1,44 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the event hub namespace event hub') +param eventHubName string + +@description('Required. The name of the consumer group') +param name string + +@description('Optional. User Metadata is a placeholder to store user-defined string data with maximum length 1024. e.g. it can be used to store descriptive data, such as list of teams and their contact information also user-defined configuration settings can be stored.') +param userMetadata string = '' + +@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 namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource eventhub 'eventHubs@2021-06-01-preview' existing = { + name: eventHubName + } +} + +resource consumerGroup 'Microsoft.EventHub/namespaces/eventhubs/consumergroups@2021-06-01-preview' = { + name: name + parent: namespace::eventhub + properties: { + userMetadata: !empty(userMetadata) ? userMetadata : null + } +} + +@description('The name of the consumer group.') +output name string = consumerGroup.name + +@description('The resource ID of the consumer group.') +output resourceId string = consumerGroup.id + +@description('The name of the resource group the consumer group was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/readme.md b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/readme.md new file mode 100644 index 000000000..e5f2311d7 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/readme.md @@ -0,0 +1,31 @@ +# EventHub Namespace EventHubs Consumer Group `[Microsoft.EventHub/namespaces/eventhubs/consumergroups]` + +This module deploys an EventHub Namespace EventHubs Consumer Group + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/eventhubs/consumergroups` | 2021-06-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 | +| `eventHubName` | string | | | Required. The name of the event hub namespace event hub | +| `name` | string | | | Required. The name of the consumer group | +| `namespaceName` | string | | | Required. The name of the event hub namespace | +| `userMetadata` | string | | | Optional. User Metadata is a placeholder to store user-defined string data with maximum length 1024. e.g. it can be used to store descriptive data, such as list of teams and their contact information also user-defined configuration settings can be stored. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the consumer group. | +| `resourceGroupName` | string | The name of the resource group the consumer group was created in. | +| `resourceId` | string | The resource ID of the consumer group. | + +## Template references + +- [Namespaces/Eventhubs/Consumergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/consumergroups) diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/version.json b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/consumergroups/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/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/deploy.bicep b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/deploy.bicep new file mode 100644 index 000000000..d12aa3496 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/deploy.bicep @@ -0,0 +1,188 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the event hub') +param name string + +@description('Optional. Authorization Rules for the event hub') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. Number of days to retain the events for this Event Hub, value should be 1 to 7 days') +@minValue(1) +@maxValue(7) +param messageRetentionInDays int = 1 + +@description('Optional. Number of partitions created for the Event Hub, allowed values are from 1 to 32 partitions.') +@minValue(1) +@maxValue(32) +param partitionCount int = 2 + +@description('Optional. Enumerates the possible values for the status of the Event Hub.') +@allowed([ + 'Active' + 'Creating' + 'Deleting' + 'Disabled' + 'ReceiveDisabled' + 'Renaming' + 'Restoring' + 'SendDisabled' + 'Unknown' +]) +param status string = 'Active' + +@description('Optional. The consumer groups to create in this event hub instance') +param consumerGroups array = [ + { + name: '$Default' + } +] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Name for capture destination') +param captureDescriptionDestinationName string = 'EventHubArchive.AzureBlockBlob' + +@description('Optional. Blob naming convention for archive, e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}. Here all the parameters (Namespace,EventHub .. etc) are mandatory irrespective of order') +param captureDescriptionDestinationArchiveNameFormat string = '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + +@description('Optional. Blob container Name') +param captureDescriptionDestinationBlobContainer string = '' + +@description('Optional. Resource ID of the storage account to be used to create the blobs') +param captureDescriptionDestinationStorageAccountResourceId string = '' + +@description('Optional. A value that indicates whether capture description is enabled.') +param captureDescriptionEnabled bool = false + +@description('Optional. Enumerates the possible values for the encoding format of capture description. Note: "AvroDeflate" will be deprecated in New API Version') +@allowed([ + 'Avro' + 'AvroDeflate' +]) +param captureDescriptionEncoding string = 'Avro' + +@description('Optional. The time window allows you to set the frequency with which the capture to Azure Blobs will happen') +@minValue(60) +@maxValue(900) +param captureDescriptionIntervalInSeconds int = 300 + +@description('Optional. The size window defines the amount of data built up in your Event Hub before an capture operation') +@minValue(10485760) +@maxValue(524288000) +param captureDescriptionSizeLimitInBytes int = 314572800 + +@description('Optional. A value that indicates whether to Skip Empty Archives') +param captureDescriptionSkipEmptyArchives bool = false + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var eventHubPropertiesSimple = { + messageRetentionInDays: messageRetentionInDays + partitionCount: partitionCount + status: status +} +var eventHubPropertiesWithCapture = { + messageRetentionInDays: messageRetentionInDays + partitionCount: partitionCount + status: status + captureDescription: { + destination: { + name: captureDescriptionDestinationName + properties: { + archiveNameFormat: captureDescriptionDestinationArchiveNameFormat + blobContainer: captureDescriptionDestinationBlobContainer + storageAccountResourceId: captureDescriptionDestinationStorageAccountResourceId + } + } + enabled: captureDescriptionEnabled + encoding: captureDescriptionEncoding + intervalInSeconds: captureDescriptionIntervalInSeconds + sizeLimitInBytes: captureDescriptionSizeLimitInBytes + skipEmptyArchives: captureDescriptionSkipEmptyArchives + } +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2021-06-01-preview' = { + name: name + parent: namespace + properties: captureDescriptionEnabled ? eventHubPropertiesWithCapture : eventHubPropertiesSimple +} + +resource eventHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${eventHub.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: eventHub +} + +module eventHub_consumergroups 'consumergroups/deploy.bicep' = [for (consumerGroup, index) in consumerGroups: { + name: '${deployment().name}-ConsumerGroup-${index}' + params: { + namespaceName: namespaceName + eventHubName: eventHub.name + name: consumerGroup.name + userMetadata: contains(consumerGroup, 'userMetadata') ? consumerGroup.userMetadata : '' + } +}] + +module eventHub_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + eventHubName: eventHub.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module eventHub_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: eventHub.id + } +}] + +@description('The name of the event hub.') +output name string = eventHub.name + +@description('The resource ID of the event hub.') +output eventHubId string = eventHub.id + +@description('The resource group the event hub was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The authentication rule resource ID of the event hub.') +output resourceId string = az.resourceId('Microsoft.EventHub/namespaces/authorizationRules', namespaceName, 'RootManageSharedAccessKey') diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/readme.md b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/readme.md new file mode 100644 index 000000000..63f6b5580 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/readme.md @@ -0,0 +1,76 @@ +# EventHub `[Microsoft.EventHub/namespaces/eventhubs]` + +This module deploys an Event Hub. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/authorizationRules` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/consumergroups` | 2021-06-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Optional. Authorization Rules for the event hub | +| `captureDescriptionDestinationArchiveNameFormat` | string | `{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}` | | Optional. Blob naming convention for archive, e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}. Here all the parameters (Namespace,EventHub .. etc) are mandatory irrespective of order | +| `captureDescriptionDestinationBlobContainer` | string | | | Optional. Blob container Name | +| `captureDescriptionDestinationName` | string | `EventHubArchive.AzureBlockBlob` | | Optional. Name for capture destination | +| `captureDescriptionDestinationStorageAccountResourceId` | string | | | Optional. Resource ID of the storage account to be used to create the blobs | +| `captureDescriptionEnabled` | bool | | | Optional. A value that indicates whether capture description is enabled. | +| `captureDescriptionEncoding` | string | `Avro` | `[Avro, AvroDeflate]` | Optional. Enumerates the possible values for the encoding format of capture description. Note: "AvroDeflate" will be deprecated in New API Version | +| `captureDescriptionIntervalInSeconds` | int | `300` | | Optional. The time window allows you to set the frequency with which the capture to Azure Blobs will happen | +| `captureDescriptionSizeLimitInBytes` | int | `314572800` | | Optional. The size window defines the amount of data built up in your Event Hub before an capture operation | +| `captureDescriptionSkipEmptyArchives` | bool | | | Optional. A value that indicates whether to Skip Empty Archives | +| `consumerGroups` | _[consumerGroups](consumerGroups/readme.md)_ array | `[System.Collections.Hashtable]` | | Optional. The consumer groups to create in this event hub instance | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `messageRetentionInDays` | int | `1` | | Optional. Number of days to retain the events for this Event Hub, value should be 1 to 7 days | +| `name` | string | | | Required. The name of the event hub | +| `namespaceName` | string | | | Required. The name of the event hub namespace | +| `partitionCount` | int | `2` | | Optional. Number of partitions created for the Event Hub, allowed values are from 1 to 32 partitions. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `status` | string | `Active` | `[Active, Creating, Deleting, Disabled, ReceiveDisabled, Renaming, Restoring, SendDisabled, Unknown]` | Optional. Enumerates the possible values for the status of the Event Hub. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `eventHubId` | string | The resource ID of the event hub. | +| `name` | string | The name of the event hub. | +| `resourceGroupName` | string | The resource group the event hub was deployed into. | +| `resourceId` | string | The authentication rule resource ID of the event hub. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces/Eventhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs) +- [Namespaces/Eventhubs/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/authorizationRules) +- [Namespaces/Eventhubs/Consumergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/consumergroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/version.json b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/eventhubs/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/carml/1.0.0/Microsoft.EventHub/namespaces/readme.md b/carml/1.0.0/Microsoft.EventHub/namespaces/readme.md new file mode 100644 index 000000000..78a37340c --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/readme.md @@ -0,0 +1,162 @@ +# Event Hub Namespaces `[Microsoft.EventHub/namespaces]` + +This module deploys an event hub namespace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventHub/namespaces` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/authorizationRules` | 2017-04-01 | +| `Microsoft.EventHub/namespaces/disasterRecoveryConfigs` | 2017-04-01 | +| `Microsoft.EventHub/namespaces/eventhubs` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/authorizationRules` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/consumergroups` | 2021-06-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Optional. Authorization Rules for the Event Hub namespace | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `disasterRecoveryConfig` | object | `{object}` | | Optional. The disaster recovery config for this namespace | +| `eventHubs` | _[eventHubs](eventHubs/readme.md)_ array | `[]` | | Optional. The event hubs to deploy into this namespace | +| `isAutoInflateEnabled` | bool | | | Optional. Switch to enable the Auto Inflate feature of Event Hub. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ArchiveLogs, OperationalLogs, KafkaCoordinatorLogs, KafkaUserErrorLogs, EventHubVNetConnectionEvent, CustomerManagedKeyUserLogs, AutoScaleLogs]` | `[ArchiveLogs, OperationalLogs, KafkaCoordinatorLogs, KafkaUserErrorLogs, EventHubVNetConnectionEvent, CustomerManagedKeyUserLogs, AutoScaleLogs]` | Optional. The name of logs that will be streamed. | +| `maximumThroughputUnits` | int | `1` | | Optional. Upper limit of throughput units when AutoInflate is enabled, value should be within 0 to 20 throughput units. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Optional. The name of the event hub namespace. If no name is provided, then unique name will be created. | +| `networkAcls` | object | `{object}` | | Optional. Service endpoint object information | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.| +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuCapacity` | int | `1` | | Optional. Event Hub plan scale-out capacity of the resource | +| `skuName` | string | `Standard` | `[Basic, Standard]` | Optional. event hub plan SKU name | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `vNetId` | string | | | Optional. Virtual Network ID to lock down the Event Hub. | +| `zoneRedundant` | bool | | | Optional. Switch to make the Event Hub Namespace zone redundant. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the eventspace. | +| `resourceGroupName` | string | The resource group where the namespace is deployed. | +| `resourceId` | string | The resource ID of the eventspace. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces) +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/authorizationRules) +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/disasterRecoveryConfigs) +- [Namespaces/Eventhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs) +- [Namespaces/Eventhubs/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/authorizationRules) +- [Namespaces/Eventhubs/Consumergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/consumergroups) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.EventHub/namespaces/version.json b/carml/1.0.0/Microsoft.EventHub/namespaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.EventHub/namespaces/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/carml/1.0.0/Microsoft.HealthBot/healthBots/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.HealthBot/healthBots/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.HealthBot/healthBots/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.HealthBot/healthBots/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.HealthBot/healthBots/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6d9805b9c --- /dev/null +++ b/carml/1.0.0/Microsoft.HealthBot/healthBots/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource healthBot 'Microsoft.HealthBot/healthBots@2021-06-10' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(healthBot.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: healthBot +}] diff --git a/carml/1.0.0/Microsoft.HealthBot/healthBots/.parameters/parameters.json b/carml/1.0.0/Microsoft.HealthBot/healthBots/.parameters/parameters.json new file mode 100644 index 000000000..76b924cc3 --- /dev/null +++ b/carml/1.0.0/Microsoft.HealthBot/healthBots/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ahb-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.HealthBot/healthBots/deploy.bicep b/carml/1.0.0/Microsoft.HealthBot/healthBots/deploy.bicep new file mode 100644 index 000000000..143837e80 --- /dev/null +++ b/carml/1.0.0/Microsoft.HealthBot/healthBots/deploy.bicep @@ -0,0 +1,67 @@ +@description('Required. Name of the resource') +param name string + +@description('Optional. The resource model definition representing SKU.') +param sku string = 'F0' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 azureHealthBot 'Microsoft.HealthBot/healthBots@2020-12-08' = { + name: name + location: location + tags: tags + sku: { + name: sku + } + properties: {} +} + +resource azureHealthBot_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureHealthBot.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureHealthBot +} + +module healthBot_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-HealthBot-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureHealthBot.id + } +}] + +@description('The resource group the health bot was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the health bot') +output name string = azureHealthBot.name + +@description('The resource ID of the health bot') +output resourceId string = azureHealthBot.id diff --git a/carml/1.0.0/Microsoft.HealthBot/healthBots/readme.md b/carml/1.0.0/Microsoft.HealthBot/healthBots/readme.md new file mode 100644 index 000000000..f6896105b --- /dev/null +++ b/carml/1.0.0/Microsoft.HealthBot/healthBots/readme.md @@ -0,0 +1,76 @@ +# Azure Health Bots `[Microsoft.HealthBot/healthBots]` + +This module deploys an Azure Health Bot. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.HealthBot/healthBots` | 2020-12-08 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the resource | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `F0` | | Optional. The resource model definition representing SKU. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the health bot | +| `resourceGroupName` | string | The resource group the health bot was deployed into | +| `resourceId` | string | The resource ID of the health bot | + +## Template references + +- [Define resources with Bicep and ARM templates](https://docs.microsoft.com/en-us/azure/templates) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.HealthBot/healthBots/version.json b/carml/1.0.0/Microsoft.HealthBot/healthBots/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.HealthBot/healthBots/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/carml/1.0.0/Microsoft.Insights/actionGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/actionGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/actionGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/actionGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Insights/actionGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4f06a27f6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/actionGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,33 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource actionGroup 'microsoft.insights/actionGroups@2019-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(actionGroup.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: actionGroup +}] diff --git a/carml/1.0.0/Microsoft.Insights/actionGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/actionGroups/.parameters/parameters.json new file mode 100644 index 000000000..32c9e7606 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/actionGroups/.parameters/parameters.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ag-x-001" + }, + "groupShortName": { + "value": "azagweux001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "emailReceivers": { + "value": [ + { + "name": "TestUser_-EmailAction-", + "emailAddress": "test.user@testcompany.com", + "useCommonAlertSchema": true + }, + { + "name": "TestUser2", + "emailAddress": "test.user2@testcompany.com", + "useCommonAlertSchema": true + } + ] + }, + "smsReceivers": { + "value": [ + { + "name": "TestUser_-SMSAction-", + "countryCode": "1", + "phoneNumber": "2345678901" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/actionGroups/deploy.bicep b/carml/1.0.0/Microsoft.Insights/actionGroups/deploy.bicep new file mode 100644 index 000000000..010a09821 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/actionGroups/deploy.bicep @@ -0,0 +1,93 @@ +@description('Required. The name of the action group.') +param name string + +@description('Required. The short name of the action group.') +param groupShortName string + +@description('Optional. Indicates whether this action group is enabled. If an action group is not enabled, then none of its receivers will receive communications.') +param enabled bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The list of email receivers that are part of this action group.') +param emailReceivers array = [] + +@description('Optional. The list of SMS receivers that are part of this action group.') +param smsReceivers array = [] + +@description('Optional. The list of webhook receivers that are part of this action group.') +param webhookReceivers array = [] + +@description('Optional. The list of ITSM receivers that are part of this action group.') +param itsmReceivers array = [] + +@description('Optional. The list of AzureAppPush receivers that are part of this action group.') +param azureAppPushReceivers array = [] + +@description('Optional. The list of AutomationRunbook receivers that are part of this action group.') +param automationRunbookReceivers array = [] + +@description('Optional. The list of voice receivers that are part of this action group.') +param voiceReceivers array = [] + +@description('Optional. The list of logic app receivers that are part of this action group.') +param logicAppReceivers array = [] + +@description('Optional. The list of function receivers that are part of this action group.') +param azureFunctionReceivers array = [] + +@description('Optional. The list of ARM role receivers that are part of this action group. Roles are Azure RBAC roles and only built-in roles are supported.') +param armRoleReceivers array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Location for all resources.') +param location string = 'global' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource actionGroup 'microsoft.insights/actionGroups@2019-06-01' = { + name: name + location: location + tags: tags + properties: { + groupShortName: groupShortName + enabled: enabled + emailReceivers: (empty(emailReceivers) ? null : emailReceivers) + smsReceivers: (empty(smsReceivers) ? null : smsReceivers) + webhookReceivers: (empty(webhookReceivers) ? null : webhookReceivers) + itsmReceivers: (empty(itsmReceivers) ? null : itsmReceivers) + azureAppPushReceivers: (empty(azureAppPushReceivers) ? null : azureAppPushReceivers) + automationRunbookReceivers: (empty(automationRunbookReceivers) ? null : automationRunbookReceivers) + voiceReceivers: (empty(voiceReceivers) ? null : voiceReceivers) + logicAppReceivers: (empty(logicAppReceivers) ? null : logicAppReceivers) + azureFunctionReceivers: (empty(azureFunctionReceivers) ? null : azureFunctionReceivers) + armRoleReceivers: (empty(armRoleReceivers) ? null : armRoleReceivers) + } +} + +module actionGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ActionGroup-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: actionGroup.id + } +}] + +@description('The resource group the action group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the action group ') +output name string = actionGroup.name + +@description('The resource ID of the action group ') +output resourceId string = actionGroup.id diff --git a/carml/1.0.0/Microsoft.Insights/actionGroups/readme.md b/carml/1.0.0/Microsoft.Insights/actionGroups/readme.md new file mode 100644 index 000000000..4cbad2087 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/actionGroups/readme.md @@ -0,0 +1,128 @@ +# Action Groups `[Microsoft.Insights/actionGroups]` + +This module deploys an Action Group. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `microsoft.insights/actionGroups` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `armRoleReceivers` | array | `[]` | | Optional. The list of ARM role receivers that are part of this action group. Roles are Azure RBAC roles and only built-in roles are supported. | +| `automationRunbookReceivers` | array | `[]` | | Optional. The list of AutomationRunbook receivers that are part of this action group. | +| `azureAppPushReceivers` | array | `[]` | | Optional. The list of AzureAppPush receivers that are part of this action group. | +| `azureFunctionReceivers` | array | `[]` | | Optional. The list of function receivers that are part of this action group. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `emailReceivers` | array | `[]` | | Optional. The list of email receivers that are part of this action group. | +| `enabled` | bool | `True` | | Optional. Indicates whether this action group is enabled. If an action group is not enabled, then none of its receivers will receive communications. | +| `groupShortName` | string | | | Required. The short name of the action group. | +| `itsmReceivers` | array | `[]` | | Optional. The list of ITSM receivers that are part of this action group. | +| `location` | string | `global` | | Optional. Location for all resources. | +| `logicAppReceivers` | array | `[]` | | Optional. The list of logic app receivers that are part of this action group. | +| `name` | string | | | Required. The name of the action group. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `smsReceivers` | array | `[]` | | Optional. The list of SMS receivers that are part of this action group. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `voiceReceivers` | array | `[]` | | Optional. The list of voice receivers that are part of this action group. | +| `webhookReceivers` | array | `[]` | | Optional. The list of webhook receivers that are part of this action group. | + +### Parameter Usage: receivers + +See [Documentation](https://docs.microsoft.com/en-us/azure/templates/microsoft.insights/2019-06-01/actiongroups) for description of parameters usage and syntax. + +Example: + +```json +"emailReceivers":{ + "value":[ + { + "name": "TestUser_-EmailAction-", + "emailAddress": "test.user@testcompany.com", + "useCommonAlertSchema": true + }, + { + "name": "TestUser2", + "emailAddress": "test.user2@testcompany.com", + "useCommonAlertSchema": true + } + ] +}, +"smsReceivers":{ + "value": [ + { + "name": "TestUser_-SMSAction-", + "countryCode": "1", + "phoneNumber": "2345678901" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Additional notes on parameters + +- Receiver name must be unique across the ActionGroup +- Email, SMS, Azure App push and Voice can be grouped in the same Action. To do so, the `name` field of the receivers must be in the `RecName_-ActionType-` format where: + - _RecName_ is the name you want to give to the Action + - _ActionType_ is one of the action types that can be grouped together. Possible values are: + - EmailAction + - SMSAction + - AzureAppAction + - VoiceAction +- To understand the impact of the `useCommonAlertSchema` field, see [here](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/alerts-common-schema) + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the action group | +| `resourceGroupName` | string | The resource group the action group was deployed into | +| `resourceId` | string | The resource ID of the action group | + +## Template references + +- [Actiongroups](https://docs.microsoft.com/en-us/azure/templates/microsoft.insights/2019-06-01/actionGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Insights/actionGroups/version.json b/carml/1.0.0/Microsoft.Insights/actionGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/actionGroups/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/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ade3b2a85 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.bicep/nested_rbac.bicep @@ -0,0 +1,33 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(activityLogAlert.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: activityLogAlert +}] diff --git a/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.parameters/parameters.json new file mode 100644 index 000000000..8d7e3e658 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/.parameters/parameters.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ala-x-001" + }, + "scopes": { + "value": [ + "/subscriptions/<>" + ] + }, + "conditions": { + "value": [ + { + "field": "category", + "equals": "Administrative" + }, + { + "field": "resourceType", + "equals": "microsoft.compute/virtualmachines" + }, + { + "field": "operationName", + "equals": "Microsoft.Compute/virtualMachines/performMaintenance/action" + } + ] + }, + "actions": { + "value": [ + { + "actionGroupId": "/subscriptions/<>/resourceGroups/validation-rg/providers/microsoft.insights/actiongroups/adp-<>-az-ag-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/activityLogAlerts/deploy.bicep b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/deploy.bicep new file mode 100644 index 000000000..9fdbed41e --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/deploy.bicep @@ -0,0 +1,76 @@ +@description('Required. The name of the alert.') +param name string + +@description('Optional. Description of the alert.') +param alertDescription string = '' + +@description('Optional. Location for all resources.') +param location string = 'global' + +@description('Optional. Indicates whether this alert is enabled.') +param enabled bool = true + +@description('Required. the list of resource IDs that this metric alert is scoped to.') +param scopes array = [ + subscription().id +] + +@description('Optional. The list of actions to take when alert triggers.') +param actions array = [] + +@description('Required. The condition that will cause this alert to activate. Array of objects') +param conditions array + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var actionGroups = [for action in actions: { + actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action + webhookProperties: contains(action, 'webhookProperties') ? action.webhookProperties : null +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = { + name: name + location: location + tags: tags + properties: { + scopes: scopes + condition: { + allOf: conditions + } + actions: { + actionGroups: actionGroups + } + enabled: enabled + description: alertDescription + } +} + +module activityLogAlert_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ActivityLogAlert-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: activityLogAlert.id + } +}] + +@description('The name of the activity log alert') +output name string = activityLogAlert.name + +@description('The resource ID of the activity log alert') +output resourceId string = activityLogAlert.id + +@description('The resource group the activity log alert was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Insights/activityLogAlerts/readme.md b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/readme.md new file mode 100644 index 000000000..a996e325b --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/readme.md @@ -0,0 +1,182 @@ +# Activity Log Alerts `[Microsoft.Insights/activityLogAlerts]` + +This module deploys an Alert based on Activity Log. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/activityLogAlerts` | 2020-10-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Optional. The list of actions to take when alert triggers. | +| `alertDescription` | string | | | Optional. Description of the alert. | +| `conditions` | array | | | Required. The condition that will cause this alert to activate. Array of objects | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enabled` | bool | `True` | | Optional. Indicates whether this alert is enabled. | +| `location` | string | `global` | | Optional. Location for all resources. | +| `name` | string | | | Required. The name of the alert. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scopes` | array | `[[subscription().id]]` | | Required. the list of resource IDs that this metric alert is scoped to. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: actions + +```json +"actions": { + "value": [ + { + "actionGroupId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/actionGroupName", + "webhookProperties": {} + } + ] +} +``` + +`webhookProperties` is optional. + +If you do only want to provide actionGroupIds, a shorthand use of the parameter is available. + +```json +"actions": { + "value": [ + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/actionGroupName" + ] +} +``` + +### Parameter Usage: conditions + +**Conditions can also be combined with logical operators `allOf` and `anyOf`** + +```json +{ + "field": "string", + "equals": "string", + "containsAny": "array" +} +``` + +Each condition can specify only one field between `equals` and `containsAny`. + +| Parameter Name | Type | Possible values | Description | +| :------------- | :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | +| `field` | string | `resourceId`,
`category`,
`caller`,
`level`,
`operationName`,
`resourceGroup`,
`resourceProvider`,
`status`,
`subStatus`,
`resourceType`,
or anything beginning with `properties.` | Required. The name of the field that this condition will examine. | +| `equals` | string | | Optional (Alternative to `containsAny`). The value to confront with. | +| `containsAny` | array of strings | | Optional (Alternative to `equals`). Condition will be satisfied if value of the field in the event is within one of the specified here. | + +**Sample** + +```json +"conditions":{ + "value": [ + { + "field": "category", + "equals": "Administrative" + }, + { + "field": "resourceType", + "equals": "microsoft.compute/virtualmachines" + }, + { + "field": "operationName", + "equals": "Microsoft.Compute/virtualMachines/performMaintenance/action" + } + ] +} +``` + +**Sample 2** + +```json +"conditions":{ + "value": [ + { + "field": "category", + "equals": "ServiceHealth" + }, + { + "anyOf": [ + { + "field": "properties.incidentType", + "equals": "Incident" + }, + { + "field": "properties.incidentType", + "equals": "Maintenance" + } + ] + }, + { + "field": "properties.impactedServices[*].ServiceName", + "containsAny": [ + "Action Groups", + "Activity Logs & Alerts" + ] + }, + { + "field": "properties.impactedServices[*].ImpactedRegions[*].RegionName", + "containsAny": [ + "West Europe", + "Global" + ] + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the activity log alert | +| `resourceGroupName` | string | The resource group the activity log alert was deployed into | +| `resourceId` | string | The resource ID of the activity log alert | + +## Template references + +- [Activitylogalerts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2020-10-01/activityLogAlerts) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Insights/activityLogAlerts/version.json b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/activityLogAlerts/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/carml/1.0.0/Microsoft.Insights/components/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/components/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/components/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/components/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Insights/components/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..3c4de64b8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/components/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Application Insights Snapshot Debugger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') +} + +resource appInsights 'Microsoft.Insights/components@2020-02-02' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appInsights.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: appInsights +}] diff --git a/carml/1.0.0/Microsoft.Insights/components/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/components/.parameters/parameters.json new file mode 100644 index 000000000..636d9f6c7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/components/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-appi-x-001" + }, + "workspaceResourceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-appi-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/components/deploy.bicep b/carml/1.0.0/Microsoft.Insights/components/deploy.bicep new file mode 100644 index 000000000..bf087644c --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/components/deploy.bicep @@ -0,0 +1,80 @@ +@description('Required. Name of the Application Insights') +param name string + +@description('Optional. Application type') +@allowed([ + 'web' + 'other' +]) +param appInsightsType string = 'web' + +@description('Required. Resource ID of the log analytics workspace which the data will be ingested to. This property is required to create an application with this API version. Applications from older versions will not have this property.') +param workspaceResourceId string + +@description('Optional. The network access type for accessing Application Insights ingestion. - Enabled or Disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Optional. The network access type for accessing Application Insights query. - Enabled or Disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Optional. The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone.') +param kind string = '' + +@description('Optional. Location for all Resources') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 appInsights 'Microsoft.Insights/components@2020-02-02' = { + name: name + location: location + tags: tags + kind: kind + properties: { + Application_Type: appInsightsType + WorkspaceResourceId: workspaceResourceId + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + } +} + +module appInsights_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppInsights-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appInsights.id + } +}] + +@description('The name of the application insights component') +output name string = appInsights.name + +@description('The resource ID of the application insights component') +output resourceId string = appInsights.id + +@description('The resource group the application insights component was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The application ID of the application insights component') +output applicationId string = appInsights.properties.AppId diff --git a/carml/1.0.0/Microsoft.Insights/components/readme.md b/carml/1.0.0/Microsoft.Insights/components/readme.md new file mode 100644 index 000000000..97acdfc37 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/components/readme.md @@ -0,0 +1,76 @@ +# Application Insights `[Microsoft.Insights/components]` + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/components` | 2020-02-02 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `publicNetworkAccessForIngestion` | string | `Enabled` | `[Enabled, Disabled]` | Optional. The network access type for accessing Application Insights ingestion. - Enabled or Disabled | +| `publicNetworkAccessForQuery` | string | `Enabled` | `[Enabled, Disabled]` | Optional. The network access type for accessing Application Insights query. - Enabled or Disabled | +| `appInsightsType` | string | `web` | `[web, other]` | Optional. Application type | +| `workspaceResourceId` | string | | | Required. Resource ID of the log analytics workspace which the data will be ingested to. This property is required to create an application with this API version. Applications from older versions will not have this property. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `kind` | string | | | Optional. The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources | +| `name` | string | | | Required. Name of the Application Insights | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationId` | string | The application ID of the application insights component | +| `name` | string | The name of the application insights component | +| `resourceGroupName` | string | The resource group the application insights component was deployed into | +| `resourceId` | string | The resource ID of the application insights component | + +## Template references + +- [Components](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2020-02-02/components) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Insights/components/version.json b/carml/1.0.0/Microsoft.Insights/components/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/components/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/carml/1.0.0/Microsoft.Insights/diagnosticSettings/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/.parameters/parameters.json new file mode 100644 index 000000000..2e1d38512 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-diag-x-001" + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/diagnosticSettings/deploy.bicep b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/deploy.bicep new file mode 100644 index 000000000..71d8eb855 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/deploy.bicep @@ -0,0 +1,74 @@ +targetScope = 'subscription' + +@description('Optional. Name of the ActivityLog diagnostic settings.') +@minLength(1) +@maxLength(260) +param name string = '${uniqueString(subscription().id)}-ActivityLog' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Administrative' + 'Security' + 'ServiceHealth' + 'Alert' + 'Recommendation' + 'Policy' + 'Autoscale' + 'ResourceHealth' +]) +param logsToEnable array = [ + 'Administrative' + 'Security' + 'ServiceHealth' + 'Alert' + 'Recommendation' + 'Policy' + 'Autoscale' + 'ResourceHealth' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource diagnosticSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: name + properties: { + storageAccountId: (empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId) + workspaceId: (empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId) + eventHubAuthorizationRuleId: (empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId) + eventHubName: (empty(diagnosticEventHubName) ? null : diagnosticEventHubName) + logs: ((empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName)) ? null : diagnosticsLogs) + } +} + +@description('The name of the diagnostic settings') +output name string = diagnosticSetting.name + +@description('The resource ID of the diagnostic settings') +output resourceId string = diagnosticSetting.id + +@description('The name of the subscription to deploy into') +output subscriptionName string = subscription().displayName diff --git a/carml/1.0.0/Microsoft.Insights/diagnosticSettings/readme.md b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/readme.md new file mode 100644 index 000000000..f225ac539 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/readme.md @@ -0,0 +1,33 @@ +# Activity Logs `[Microsoft.Insights/diagnosticSettings]` + +This module deploys a subscription wide export of the activity log. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `logsToEnable` | array | `[Administrative, Security, ServiceHealth, Alert, Recommendation, Policy, Autoscale, ResourceHealth]` | `[Administrative, Security, ServiceHealth, Alert, Recommendation, Policy, Autoscale, ResourceHealth]` | Optional. The name of logs that will be streamed. | +| `name` | string | `[format('{0}-ActivityLog', uniqueString(subscription().id))]` | | Optional. Name of the ActivityLog diagnostic settings. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the diagnostic settings | +| `resourceId` | string | The resource ID of the diagnostic settings | +| `subscriptionName` | string | The name of the subscription to deploy into | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) diff --git a/carml/1.0.0/Microsoft.Insights/diagnosticSettings/version.json b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/diagnosticSettings/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/carml/1.0.0/Microsoft.Insights/metricAlerts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/metricAlerts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/metricAlerts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/metricAlerts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Insights/metricAlerts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..aecb16dee --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/metricAlerts/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource metricAlert 'Microsoft.Insights/metricAlerts@2018-03-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(metricAlert.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: metricAlert +}] diff --git a/carml/1.0.0/Microsoft.Insights/metricAlerts/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/metricAlerts/.parameters/parameters.json new file mode 100644 index 000000000..bbe65cdae --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/metricAlerts/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ma-x-001" + }, + "windowSize": { + "value": "PT15M" + }, + "actions": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/microsoft.insights/actiongroups/adp-<>-az-ag-x-001" + ] + }, + "targetResourceType": { + "value": "microsoft.compute/virtualmachines" + }, + "targetResourceRegion": { + "value": "westeurope" + }, + "criterias": { + "value": [ + { + "criterionType": "StaticThresholdCriterion", + "metricName": "Percentage CPU", + "metricNamespace": "microsoft.compute/virtualmachines", + "name": "HighCPU", + "operator": "GreaterThan", + "threshold": "90", + "timeAggregation": "Average" + } + ] + }, + "alertCriteriaType": { + "value": "Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/metricAlerts/deploy.bicep b/carml/1.0.0/Microsoft.Insights/metricAlerts/deploy.bicep new file mode 100644 index 000000000..091a04e70 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/metricAlerts/deploy.bicep @@ -0,0 +1,131 @@ +@description('Required. The name of the alert.') +param name string + +@description('Optional. Description of the alert.') +param alertDescription string = '' + +@description('Optional. Location for all resources.') +param location string = 'global' + +@description('Optional. Indicates whether this alert is enabled.') +param enabled bool = true + +@description('Optional. The severity of the alert.') +@allowed([ + 0 + 1 + 2 + 3 + 4 +]) +param severity int = 3 + +@description('Optional. how often the metric alert is evaluated represented in ISO 8601 duration format.') +@allowed([ + 'PT1M' + 'PT5M' + 'PT15M' + 'PT30M' + 'PT1H' +]) +param evaluationFrequency string = 'PT5M' + +@description('Optional. the period of time (in ISO 8601 duration format) that is used to monitor alert activity based on the threshold.') +@allowed([ + 'PT1M' + 'PT5M' + 'PT15M' + 'PT30M' + 'PT1H' + 'PT6H' + 'PT12H' + 'P1D' +]) +param windowSize string = 'PT15M' + +@description('Optional. the list of resource IDs that this metric alert is scoped to.') +param scopes array = [ + subscription().id +] + +@description('Optional. The resource type of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria.') +param targetResourceType string = '' + +@description('Optional. The region of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria.') +param targetResourceRegion string = '' + +@description('Optional. The flag that indicates whether the alert should be auto resolved or not.') +param autoMitigate bool = true + +@description('Optional. The list of actions to take when alert triggers.') +param actions array = [] + +@description('Optional. Maps to the \'odata.type\' field. Specifies the type of the alert criteria.') +@allowed([ + 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria' + 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' + 'Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria' +]) +param alertCriteriaType string = 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' + +@description('Required. Criterias to trigger the alert. Array of \'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria\' or \'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria\' objects') +param criterias array + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var actionGroups = [for action in actions: { + actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action + webHookProperties: contains(action, 'webHookProperties') ? action.webHookProperties : null +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource metricAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = { + name: name + location: location + tags: tags + properties: { + description: alertDescription + severity: severity + enabled: enabled + scopes: scopes + evaluationFrequency: evaluationFrequency + windowSize: windowSize + targetResourceType: targetResourceType + targetResourceRegion: targetResourceRegion + criteria: { + 'odata.type': alertCriteriaType + allOf: criterias + } + autoMitigate: autoMitigate + actions: actionGroups + } +} + +module metricAlert_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-MetricAlert-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: metricAlert.id + } +}] + +@description('The resource group the metric alert was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the metric alert') +output name string = metricAlert.name + +@description('The resource ID of the metric alert') +output resourceId string = metricAlert.id diff --git a/carml/1.0.0/Microsoft.Insights/metricAlerts/readme.md b/carml/1.0.0/Microsoft.Insights/metricAlerts/readme.md new file mode 100644 index 000000000..e8f7b4c2b --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/metricAlerts/readme.md @@ -0,0 +1,172 @@ +# Metric Alerts `[Microsoft.Insights/metricAlerts]` + +This module deploys an alert based on metrics. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/metricAlerts` | 2018-03-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Optional. The list of actions to take when alert triggers. | +| `alertCriteriaType` | string | `Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria` | `[Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria, Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria, Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria]` | Optional. Maps to the 'odata.type' field. Specifies the type of the alert criteria. | +| `alertDescription` | string | | | Optional. Description of the alert. | +| `autoMitigate` | bool | `True` | | Optional. The flag that indicates whether the alert should be auto resolved or not. | +| `criterias` | array | | | Required. Criterias to trigger the alert. Array of 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria' or 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' objects | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enabled` | bool | `True` | | Optional. Indicates whether this alert is enabled. | +| `evaluationFrequency` | string | `PT5M` | `[PT1M, PT5M, PT15M, PT30M, PT1H]` | Optional. how often the metric alert is evaluated represented in ISO 8601 duration format. | +| `location` | string | `global` | | Optional. Location for all resources. | +| `name` | string | | | Required. The name of the alert. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scopes` | array | `[[subscription().id]]` | | Optional. the list of resource IDs that this metric alert is scoped to. | +| `severity` | int | `3` | `[0, 1, 2, 3, 4]` | Optional. The severity of the alert. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `targetResourceRegion` | string | | | Optional. The region of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria. | +| `targetResourceType` | string | | | Optional. The resource type of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria. | +| `windowSize` | string | `PT15M` | `[PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D]` | Optional. the period of time (in ISO 8601 duration format) that is used to monitor alert activity based on the threshold. | + +### Parameter Usage: actions + +```json +"actions": { + "value": [ + { + "actionGroupId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/ActionGroupName", + "webhookProperties": {} + } + ] +} +``` + +`webhookProperties` is optional. + +If you do only want to provide actionGroupIds, a shorthand use of the parameter is available. + +```json +"actions": { + "value": [ + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/actionGroupName" + ] +} +``` + +### Parameter Usage: criterias + +**SingleResourceMultipleMetricCriteria** + +```json +{ + "criterionType": "string", + "dimensions": [], + "metricName": "string", + "metricNamespace": "string", + "name": "string", + "operator": "string", + "threshold": "integer", + "timeAggregation": "string" +} +``` + +**MultipleResourceMultipleMetricCriteria** + +```json +{ + "criterionType": "string", + "dimensions": [], + "metricName": "string", + "metricNamespace": "string", + "name": "string", + "operator": "string", + "threshold": "integer", + "timeAggregation": "string", + "alertSensitivity": "string", + "failingPeriods": { + "minFailingPeriodsToAlert": "integer", + "numberOfEvaluationPeriods": "integer" + }, + "ignoreDataBefore": "string" +} +``` + +**Sample** +The following sample can be use both for Single and Multiple criterias. The other parameters are optional. + +```json +"criterias":{ + "value": [ + { + "criterionType": "StaticThresholdCriterion", + "metricName": "Percentage CPU", + "metricNamespace": "microsoft.compute/virtualmachines", + "name": "HighCPU", + "operator": "GreaterThan", + "threshold": "90", + "timeAggregation": "Average" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Additional notes on parameters + +- When using MultipleResourceMultipleMetricCriteria criteria type, some parameters becomes mandatory (see above) +- MultipleResourceMultipleMetricCriteria is suggested, as additional scopes can be added later +- It's not possible to convert from SingleResourceMultipleMetricCriteria to MultipleResourceMultipleMetricCriteria. Delete and re-create the alert. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the metric alert | +| `resourceGroupName` | string | The resource group the metric alert was deployed into | +| `resourceId` | string | The resource ID of the metric alert | + +## Template references + +- [Metricalerts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2018-03-01/metricAlerts) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Insights/metricAlerts/version.json b/carml/1.0.0/Microsoft.Insights/metricAlerts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/metricAlerts/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/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..5672ec5ea --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateDnsZoneGroups 'privateDnsZoneGroups@2021-05-01' = { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..479082e69 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateLinkScope 'Microsoft.Insights/privateLinkScopes@2019-10-17-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateLinkScope.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: privateLinkScope +}] diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.parameters/parameters.json new file mode 100644 index 000000000..26b710302 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/.parameters/parameters.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pls-x-001" + }, + "scopedResources": { + "value": [ + { + "name": "scoped1", + "linkedResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/deploy.bicep b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/deploy.bicep new file mode 100644 index 000000000..b07aa6c90 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/deploy.bicep @@ -0,0 +1,87 @@ +@description('Required. Name of the private link scope.') +@minLength(1) +param name string + +@description('Optional. The location of the private link scope. Should be global.') +param location string = 'global' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for Azure Monitor Resources.') +param scopedResources array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@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 privateLinkScope 'Microsoft.Insights/privateLinkScopes@2019-10-17-preview' = { + name: name + location: location + tags: tags + properties: {} +} + +module privateLinkScope_scopedResource 'scopedResources/deploy.bicep' = [for (scopedResource, index) in scopedResources: { + name: '${uniqueString(deployment().name, location)}-PvtLinkScope-ScopedRes-${index}' + params: { + name: scopedResource.name + privateLinkScopeName: privateLinkScope.name + linkedResourceId: scopedResource.linkedResourceId + } +}] + +resource privateLinkScope_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateLinkScope.name}-${lock}-lock' + scope: privateLinkScope + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } +} + +module privateLinkScope_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-PvtLinkScope-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: privateLinkScope.id + privateEndpointVnetLocation: reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: endpoint + tags: tags + } +}] + +module privateLinkScope_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PvtLinkScope-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateLinkScope.id + } +}] + +@description('The name of the private link scope') +output name string = privateLinkScope.name + +@description('The resource ID of the private link scope') +output resourceId string = privateLinkScope.id + +@description('The resource group the private link scope was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/readme.md b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/readme.md new file mode 100644 index 000000000..6d16bbd4e --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/readme.md @@ -0,0 +1,119 @@ +# Azure Monitor Private Link Scopes `[Microsoft.Insights/privateLinkScopes]` + +This module deploys an Azure Monitor Private Link Scope. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `microsoft.insights/privateLinkScopes` | 2019-10-17-preview | +| `Microsoft.Insights/privateLinkScopes/scopedResources` | 2021-07-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `global` | | Optional. The location of the private link scope. Should be global. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the private link scope. | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scopedResources` | _[scopedResources](scopedResources/readme.md)_ array | `[]` | | Optional. Configuration Details for Azure Monitor Resources. | +| `tags` | object | `{object}` | | Optional. Resource tags. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private link scope | +| `resourceGroupName` | string | The resource group the private link scope was deployed into | +| `resourceId` | string | The resource ID of the private link scope | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Privatelinkscopes](https://docs.microsoft.com/en-us/azure/templates/microsoft.insights/2019-10-17-preview/privateLinkScopes) +- [Privatelinkscopes/Scopedresources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-07-01-preview/privateLinkScopes/scopedResources) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/deploy.bicep b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/deploy.bicep new file mode 100644 index 000000000..edfe4ddec --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/deploy.bicep @@ -0,0 +1,39 @@ +@description('Required. Name of the private link scoped resource.') +@minLength(1) +param name string + +@description('Required. Name of the parent private link scope.') +@minLength(1) +param privateLinkScopeName string + +@description('Required. The resource ID of the scoped Azure monitor resource.') +param linkedResourceId string + +@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 privateLinkScope 'microsoft.insights/privateLinkScopes@2021-07-01-preview' existing = { + name: privateLinkScopeName +} + +resource scopedResource 'Microsoft.Insights/privateLinkScopes/scopedResources@2021-07-01-preview' = { + name: name + parent: privateLinkScope + properties: { + linkedResourceId: linkedResourceId + } +} + +@description('The name of the resource group where the resource has been deployed') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the deployed scopedResource') +output resourceId string = scopedResource.id + +@description('The full name of the deployed Scoped Resource') +output name string = scopedResource.name diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/readme.md b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/readme.md new file mode 100644 index 000000000..dda21bef8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/readme.md @@ -0,0 +1,30 @@ +# Insights PrivateLinkScopes ScopedResources `[Microsoft.Insights/privateLinkScopes/scopedResources]` + +This module deploys Insights PrivateLinkScopes ScopedResources. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/privateLinkScopes/scopedResources` | 2021-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 | +| `linkedResourceId` | string | | | Required. The resource ID of the scoped Azure monitor resource. | +| `name` | string | | | Required. Name of the private link scoped resource. | +| `privateLinkScopeName` | string | | | Required. Name of the parent private link scope. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The full name of the deployed Scoped Resource | +| `resourceGroupName` | string | The name of the resource group where the resource has been deployed | +| `resourceId` | string | The resource ID of the deployed scopedResource | + +## Template references + +- [Privatelinkscopes/Scopedresources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-07-01-preview/privateLinkScopes/scopedResources) diff --git a/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/version.json b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/scopedResources/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/carml/1.0.0/Microsoft.Insights/privateLinkScopes/version.json b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/privateLinkScopes/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/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b7c9097a8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource queryAlert 'microsoft.insights/scheduledQueryRules@2018-04-16' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queryAlert.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: queryAlert +}] diff --git a/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.parameters/parameters.json b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.parameters/parameters.json new file mode 100644 index 000000000..85cb87625 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/.parameters/parameters.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "myAlert01" + }, + "alertDescription": { + "value": "My sample Alert" + }, + "scopes": { + "value": [ + "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + ] + }, + "evaluationFrequency": { + "value": "PT5M" + }, + "windowSize": { + "value": "PT5M" + }, + "suppressForMinutes": { + "value": "PT5M" + }, + "queryTimeRange": { + "value": "PT5M" + }, + "autoMitigate": { + "value": false + }, + "criterias": { + "value": { + "allOf": [ + { + "query": "Perf | where ObjectName == \"LogicalDisk\" | where CounterName == \"% Free Space\" | where InstanceName <> \"HarddiskVolume1\" and InstanceName <> \"_Total\" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)", + "timeAggregation": "Average", + "metricMeasureColumn": "AggregatedValue", + "dimensions": [ + { + "name": "Computer", + "operator": "Include", + "values": [ + "*" + ] + }, + { + "name": "InstanceName", + "operator": "Include", + "values": [ + "*" + ] + } + ], + "operator": "GreaterThan", + "threshold": 0 + } + ] + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/deploy.bicep b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/deploy.bicep new file mode 100644 index 000000000..6922ff77e --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/deploy.bicep @@ -0,0 +1,117 @@ +@description('Required. The name of the Alert.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The description of the scheduled query rule.') +param alertDescription string = '' + +@description('Optional. The flag which indicates whether this scheduled query rule is enabled.') +param enabled bool = true + +@description('Optional. Indicates the type of scheduled query rule.') +@allowed([ + 'LogAlert' + 'LogToMetric' +]) +param kind string = 'LogAlert' + +@description('Optional. The flag that indicates whether the alert should be automatically resolved or not. Relevant only for rules of the kind LogAlert.') +param autoMitigate bool = true + +@description('Optional. If specified (in ISO 8601 duration format) then overrides the query time range. Relevant only for rules of the kind LogAlert.') +param queryTimeRange string + +@description('Optional. The flag which indicates whether the provided query should be validated or not. Relevant only for rules of the kind LogAlert.') +param skipQueryValidation bool = false + +@description('Optional. List of resource type of the target resource(s) on which the alert is created/updated. For example if the scope is a resource group and targetResourceTypes is Microsoft.Compute/virtualMachines, then a different alert will be fired for each virtual machine in the resource group which meet the alert criteria. Relevant only for rules of the kind LogAlert') +param targetResourceTypes array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Required. The list of resource IDs that this scheduled query rule is scoped to.') +param scopes array = [] + +@description('Optional. Severity of the alert. Should be an integer between [0-4]. Value of 0 is severest. Relevant and required only for rules of the kind LogAlert.') +@allowed([ + 0 + 1 + 2 + 3 + 4 +]) +param severity int = 3 + +@description('Optional. How often the scheduled query rule is evaluated represented in ISO 8601 duration format. Relevant and required only for rules of the kind LogAlert.') +param evaluationFrequency string = '' + +@description('Optional. The period of time (in ISO 8601 duration format) on which the Alert query will be executed (bin size). Relevant and required only for rules of the kind LogAlert.') +param windowSize string + +@description('Optional. Actions to invoke when the alert fires.') +param actions array = [] + +@description('Optional. The rule criteria that defines the conditions of the scheduled query rule.') +param criterias object = {} + +@description('Optional. Mute actions for the chosen period of time (in ISO 8601 duration format) after the alert is fired. If set, autoMitigate must be disabled.Relevant only for rules of the kind LogAlert.') +param suppressForMinutes string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 queryRule 'Microsoft.Insights/scheduledQueryRules@2021-02-01-preview' = { + name: name + location: location + tags: tags + kind: kind + properties: { + actions: { + actionGroups: actions + customProperties: {} + } + autoMitigate: (kind == 'LogAlert') ? autoMitigate : null + criteria: criterias + + description: alertDescription + displayName: name + enabled: enabled + evaluationFrequency: (kind == 'LogAlert') ? evaluationFrequency : null + muteActionsDuration: (kind == 'LogAlert') ? suppressForMinutes : null + overrideQueryTimeRange: (kind == 'LogAlert') ? queryTimeRange : null + scopes: scopes + severity: (kind == 'LogAlert') ? severity : null + skipQueryValidation: (kind == 'LogAlert') ? skipQueryValidation : null + targetResourceTypes: (kind == 'LogAlert') ? targetResourceTypes : null + windowSize: (kind == 'LogAlert') ? windowSize : null + } +} + +module queryRule_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-QueryRule-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: queryRule.id + } +}] + +@description('The Name of the created query rule.') +output name string = queryRule.name + +@description('The resource ID of the created query rule.') +output resourceId string = queryRule.id + +@description('The Resource Group of the created query rule.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/readme.md b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/readme.md new file mode 100644 index 000000000..d7d16e287 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/readme.md @@ -0,0 +1,86 @@ +# Scheduled Query Rules `[Microsoft.Insights/scheduledQueryRules]` + +This module deploys a scheduled query rule. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/scheduledQueryRules` | 2021-02-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Optional. Actions to invoke when the alert fires. | +| `alertDescription` | string | | | Optional. The description of the scheduled query rule. | +| `autoMitigate` | bool | `True` | | Optional. The flag that indicates whether the alert should be automatically resolved or not. Relevant only for rules of the kind LogAlert. | +| `criterias` | object | `{object}` | | Optional. The rule criteria that defines the conditions of the scheduled query rule. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enabled` | bool | `True` | | Optional. The flag which indicates whether this scheduled query rule is enabled. | +| `evaluationFrequency` | string | | | Optional. How often the scheduled query rule is evaluated represented in ISO 8601 duration format. Relevant and required only for rules of the kind LogAlert. | +| `kind` | string | `LogAlert` | `[LogAlert, LogToMetric]` | Optional. Indicates the type of scheduled query rule. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | | | Required. The name of the Alert. | +| `queryTimeRange` | string | | | Optional. If specified (in ISO 8601 duration format) then overrides the query time range. Relevant only for rules of the kind LogAlert. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scopes` | array | `[]` | | Required. The list of resource IDs that this scheduled query rule is scoped to. | +| `severity` | int | `3` | `[0, 1, 2, 3, 4]` | Optional. Severity of the alert. Should be an integer between [0-4]. Value of 0 is severest. Relevant and required only for rules of the kind LogAlert. | +| `skipQueryValidation` | bool | | | Optional. The flag which indicates whether the provided query should be validated or not. Relevant only for rules of the kind LogAlert. | +| `suppressForMinutes` | string | | | Optional. Mute actions for the chosen period of time (in ISO 8601 duration format) after the alert is fired. If set, autoMitigate must be disabled.Relevant only for rules of the kind LogAlert. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `targetResourceTypes` | array | `[]` | | Optional. List of resource type of the target resource(s) on which the alert is created/updated. For example if the scope is a resource group and targetResourceTypes is Microsoft.Compute/virtualMachines, then a different alert will be fired for each virtual machine in the resource group which meet the alert criteria. Relevant only for rules of the kind LogAlert | +| `windowSize` | string | | | Optional. The period of time (in ISO 8601 duration format) on which the Alert query will be executed (bin size). Relevant and required only for rules of the kind LogAlert. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the created query rule. | +| `resourceGroupName` | string | The Resource Group of the created query rule. | +| `resourceId` | string | The resource ID of the created query rule. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Scheduledqueryrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-02-01-preview/scheduledQueryRules) diff --git a/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/version.json b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Insights/scheduledQueryRules/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/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..0e3f625a3 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } +} diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..2af08d083 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep @@ -0,0 +1,43 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Crypto Service Encryption User (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') + 'Key Vault Crypto User (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + 'Key Vault Reader (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Key Vault Secrets User (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(keyVault.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: keyVault +}] diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.KeyVault/vaults/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/.parameters/parameters.json b/carml/1.0.0/Microsoft.KeyVault/vaults/.parameters/parameters.json new file mode 100644 index 000000000..bf0ceca37 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/.parameters/parameters.json @@ -0,0 +1,125 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-kvlt-x-001" + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "enableRbacAuthorization": { + "value": false + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "vault" + } + ] + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "secrets": { + "value": { + "secureList": [ + { + "name": "secretName", + "value": "secretValue", + "contentType": "Something", + "attributesExp": 1702648632, + "attributesNbf": 10000, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + } + }, + "keys": { + "value": [ + { + "name": "keyName", + "attributesExp": 1702648632, + "attributesNbf": 10000, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "accessPolicies": { + "value": [ + { + "objectId": "<>", + "permissions": { + "keys": [ + "get", + "list", + "update" + ], + "secrets": [ + "all" + ] + }, + "tenantId": "<>" + }, + { + "objectId": "<>", + "permissions": { + "certificates": [ + "backup", + "create", + "delete" + ], + "secrets": [ + "all" + ] + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep new file mode 100644 index 000000000..fa3db9a84 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep @@ -0,0 +1,44 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. The access policy deployment') +param name string = 'add' + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +module pid_cuaId './.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the access policies assignment') +output name string = policies.name + +@description('The resource ID of the access policies assignment') +output resourceId string = policies.id diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/readme.md b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/readme.md new file mode 100644 index 000000000..57066308e --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/readme.md @@ -0,0 +1,56 @@ +# Key Vault Access Policies `[Microsoft.KeyVault/vaults/accessPolicies]` + +This module deploys key vault access policies. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `accessPolicies` | array | `[]` | | Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `keyVaultName` | string | | | Required. The name of the key vault | +| `name` | string | `add` | | Optional. The access policy deployment | + + +### Parameter Usage: `accessPolicies` + +```json +"accessPolicies": { + "value": [ + { + "tenantId": null, // Optional + "applicationId": null, // Optional + "objectId": null, + "permissions": { + "certificates": [ + "All" + ], + "keys": [ + "All" + ], + "secrets": [ + "All" + ] + } + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the access policies assignment | +| `resourceGroupName` | string | The name of the resource group the access policies assignment was created in. | +| `resourceId` | string | The resource ID of the access policies assignment | + +## Template references + +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/version.json b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/accessPolicies/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/carml/1.0.0/Microsoft.KeyVault/vaults/deploy.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/deploy.bicep new file mode 100644 index 000000000..3a492ec5e --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/deploy.bicep @@ -0,0 +1,284 @@ +@description('Optional. Name of the Key Vault. If no name is provided, then unique name will be created.') +@maxLength(24) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of access policies object') +param accessPolicies array = [] + +@description('Optional. All secrets to create') +@secure() +param secrets object = {} + +@description('Optional. All keys to create') +param keys array = [] + +@description('Optional. Specifies if the vault is enabled for deployment by script or compute') +@allowed([ + true + false +]) +param enableVaultForDeployment bool = true + +@description('Optional. Specifies if the vault is enabled for a template deployment') +@allowed([ + true + false +]) +param enableVaultForTemplateDeployment bool = true + +@description('Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios.') +@allowed([ + true + false +]) +param enableVaultForDiskEncryption bool = true + +@description('Optional. Switch to enable/disable Key Vault\'s soft delete feature.') +param enableSoftDelete bool = true + +@description('Optional. softDelete data retention days. It accepts >=7 and <=90.') +param softDeleteRetentionInDays int = 90 + +@description('Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC.') +param enableRbacAuthorization bool = false + +@description('Optional. The vault\'s create mode to indicate whether the vault need to be recovered or not. - recover or default.') +param createMode string = 'default' + +@description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature.') +param enablePurgeProtection bool = false + +@description('Optional. Specifies the SKU for the vault') +@allowed([ + 'premium' + 'standard' +]) +param vaultSku string = 'premium' + +@description('Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny') +param networkAcls object = {} + +@description('Optional. Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well') +param vNetId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AuditEvent' +]) +param logsToEnable array = [ + 'AuditEvent' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var maxNameLength = 24 +var uniquenameUntrim = uniqueString('Key Vault${baseTime}') +var uniquename = (length(uniquenameUntrim) > maxNameLength ? substring(uniquenameUntrim, 0, maxNameLength) : uniquenameUntrim) +var name_var = empty(name) ? uniquename : name +var virtualNetworkRules = [for networkrule in ((contains(networkAcls, 'virtualNetworkRules')) ? networkAcls.virtualNetworkRules : []): { + id: '${vNetId}/subnets/${networkrule.subnet}' +}] +var networkAcls_var = { + bypass: (empty(networkAcls) ? null : networkAcls.bypass) + defaultAction: (empty(networkAcls) ? null : networkAcls.defaultAction) + virtualNetworkRules: (empty(networkAcls) ? null : virtualNetworkRules) + ipRules: (empty(networkAcls) ? null : ((length(networkAcls.ipRules) == 0) ? [] : networkAcls.ipRules)) +} + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +var secretList = !empty(secrets) ? secrets.secureList : [] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { + name: name_var + location: location + tags: tags + properties: { + enabledForDeployment: enableVaultForDeployment + enabledForTemplateDeployment: enableVaultForTemplateDeployment + enabledForDiskEncryption: enableVaultForDiskEncryption + enableSoftDelete: enableSoftDelete + softDeleteRetentionInDays: softDeleteRetentionInDays + enableRbacAuthorization: enableRbacAuthorization + createMode: createMode + enablePurgeProtection: ((!enablePurgeProtection) ? null : enablePurgeProtection) + tenantId: subscription().tenantId + accessPolicies: formattedAccessPolicies + sku: { + name: vaultSku + family: 'A' + } + networkAcls: (empty(networkAcls) ? null : networkAcls_var) + } +} + +resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${keyVault.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: keyVault +} + +resource keyVault_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${name_var}-diagnosticSettingName' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: keyVault +} + +module keyVault_accessPolicies 'accessPolicies/deploy.bicep' = if (!empty(accessPolicies)) { + name: '${uniqueString(deployment().name, location)}-KeyVault-AccessPolicies' + params: { + keyVaultName: keyVault.name + accessPolicies: formattedAccessPolicies + } +} + +module keyVault_secrets 'secrets/deploy.bicep' = [for (secret, index) in secretList: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Secret-${index}' + params: { + name: secret.name + value: secret.value + keyVaultName: keyVault.name + attributesEnabled: contains(secret, 'attributesEnabled') ? secret.attributesEnabled : true + attributesExp: contains(secret, 'attributesExp') ? secret.attributesExp : -1 + attributesNbf: contains(secret, 'attributesNbf') ? secret.attributesNbf : -1 + contentType: contains(secret, 'contentType') ? secret.contentType : '' + tags: contains(secret, 'tags') ? secret.tags : {} + roleAssignments: contains(secret, 'roleAssignments') ? secret.roleAssignments : [] + } +}] + +module keyVault_keys 'keys/deploy.bicep' = [for (key, index) in keys: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Key-${index}' + params: { + name: key.name + keyVaultName: keyVault.name + attributesEnabled: contains(key, 'attributesEnabled') ? key.attributesEnabled : true + attributesExp: contains(key, 'attributesExp') ? key.attributesExp : -1 + attributesNbf: contains(key, 'attributesNbf') ? key.attributesNbf : -1 + curveName: contains(key, 'curveName') ? key.curveName : 'P-256' + keyOps: contains(key, 'keyOps') ? key.keyOps : [] + keySize: contains(key, 'keySize') ? key.keySize : -1 + kty: contains(key, 'kty') ? key.kty : 'EC' + tags: contains(key, 'tags') ? key.tags : {} + roleAssignments: contains(key, 'roleAssignments') ? key.roleAssignments : [] + } +}] + +module keyVault_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: keyVault.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module keyVault_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: keyVault.id + } +}] + +@description('The resource ID of the key vault.') +output resourceId string = keyVault.id + +@description('The name of the resource group the key vault was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the key vault.') +output name string = keyVault.name + +@description('The URI of the key vault.') +output uri string = keyVault.properties.vaultUri diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..2a1cbd931 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Crypto Service Encryption User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') + 'Key Vault Crypto User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource key 'Microsoft.KeyVault/vaults/keys@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(key.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: key +}] diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/keys/deploy.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/deploy.bicep new file mode 100644 index 000000000..4f4a21516 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/deploy.bicep @@ -0,0 +1,100 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Required. The name of the key') +param name string + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Determines whether the object is enabled.') +param attributesEnabled bool = true + +@description('Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible.') +param attributesExp int = -1 + +@description('Optional. Not before date in seconds since 1970-01-01T00:00:00Z.') +param attributesNbf int = -1 + +@description('Optional. The elliptic curve name.') +@allowed([ + 'P-256' + 'P-256K' + 'P-384' + 'P-521' +]) +param curveName string = 'P-256' + +@description('Optional. Array of JsonWebKeyOperation') +@allowed([ + 'decrypt' + 'encrypt' + 'import' + 'sign' + 'unwrapKey' + 'verify' + 'wrapKey' +]) +param keyOps array = [] + +@description('Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA.') +param keySize int = -1 + +@description('Optional. The type of the key.') +@allowed([ + 'EC' + 'EC-HSM' + 'RSA' + 'RSA-HSM' +]) +param kty string = 'EC' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource key 'Microsoft.KeyVault/vaults/keys@2019-09-01' = { + name: name + parent: keyVault + tags: tags + properties: { + attributes: { + enabled: attributesEnabled + exp: !(attributesExp == -1) ? attributesExp : null + nbf: !(attributesNbf == -1) ? attributesNbf : null + } + curveName: curveName + keyOps: keyOps + keySize: !(keySize == -1) ? keySize : null + kty: kty + } +} + +module key_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: key.id + } +}] + +@description('The name of the key.') +output name string = key.name + +@description('The resource ID of the key.') +output resourceId string = key.id + +@description('The name of the resource group the key was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/keys/readme.md b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/readme.md new file mode 100644 index 000000000..1c24f0ee8 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/readme.md @@ -0,0 +1,79 @@ +# Key Vault Key `[Microsoft.KeyVault/vaults/keys]` + +This module deploys a key vault key. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.KeyVault/vaults/keys` | 2019-09-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `attributesEnabled` | bool | `True` | | Optional. Determines whether the object is enabled. | +| `attributesExp` | int | `-1` | | Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible. | +| `attributesNbf` | int | `-1` | | Optional. Not before date in seconds since 1970-01-01T00:00:00Z. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `curveName` | string | `P-256` | `[P-256, P-256K, P-384, P-521]` | Optional. The elliptic curve name. | +| `keyOps` | array | `[]` | `[decrypt, encrypt, import, sign, unwrapKey, verify, wrapKey]` | Optional. Array of JsonWebKeyOperation | +| `keySize` | int | `-1` | | Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA. | +| `keyVaultName` | string | | | Required. The name of the key vault | +| `kty` | string | `EC` | `[EC, EC-HSM, RSA, RSA-HSM]` | Optional. The type of the key. | +| `name` | string | | | Required. The name of the key | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Resource tags. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the key. | +| `resourceGroupName` | string | The name of the resource group the key was created in. | +| `resourceId` | string | The resource ID of the key. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/keys) diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/keys/version.json b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/keys/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/carml/1.0.0/Microsoft.KeyVault/vaults/readme.md b/carml/1.0.0/Microsoft.KeyVault/vaults/readme.md new file mode 100644 index 000000000..8a4b0cb4f --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/readme.md @@ -0,0 +1,197 @@ +# Key Vaults `[Microsoft.KeyVault/vaults]` + +This module deploys a key vault and its child resources. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.KeyVault/vaults` | 2019-09-01 | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | +| `Microsoft.KeyVault/vaults/keys` | 2019-09-01 | +| `Microsoft.KeyVault/vaults/secrets` | 2019-09-01 | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `accessPolicies` | _[accessPolicies](accessPolicies/readme.md)_ array | `[]` | | Optional. Array of access policies object | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules. | +| `createMode` | string | `default` | | Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enablePurgeProtection` | bool | | | Optional. Provide 'true' to enable Key Vault's purge protection feature. | +| `enableRbacAuthorization` | bool | | | Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC. | +| `enableSoftDelete` | bool | `True` | | Optional. Switch to enable/disable Key Vault's soft delete feature. | +| `enableVaultForDeployment` | bool | `True` | `[True, False]` | Optional. Specifies if the vault is enabled for deployment by script or compute | +| `enableVaultForDiskEncryption` | bool | `True` | `[True, False]` | Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios. | +| `enableVaultForTemplateDeployment` | bool | `True` | `[True, False]` | Optional. Specifies if the vault is enabled for a template deployment | +| `keys` | _[keys](keys/readme.md)_ array | `[]` | | Optional. All keys to create | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[AuditEvent]` | `[AuditEvent]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Optional. Name of the Key Vault. If no name is provided, then unique name will be created. | +| `networkAcls` | object | `{object}` | | Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `secrets` | _[secrets](secrets/readme.md)_ object | `[]` | | Optional. All secrets to create | +| `softDeleteRetentionInDays` | int | `90` | | Optional. softDelete data retention days. It accepts >=7 and <=90. | +| `tags` | object | `{object}` | | Optional. Resource tags. | +| `vaultSku` | string | `premium` | `[premium, standard]` | Optional. Specifies the SKU for the vault | +| `vNetId` | string | | | Optional. Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "subnet": "sharedsvcs" + } + ], + "ipRules": [] + } +} +``` + +### Parameter Usage: `vNetId` + +```json +"vNetId": { + "value": "/subscriptions/00000000/resourceGroups/resourceGroup" +} +``` + +### Parameter Usage: `accessPolicies` + +```json +"accessPolicies": { + "value": [ + { + "tenantId": null, // Optional + "applicationId": null, // Optional + "objectId": null, + "permissions": { + "certificates": [ + "All" + ], + "keys": [ + "All" + ], + "secrets": [ + "All" + ] + } + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the key vault. | +| `resourceGroupName` | string | The name of the resource group the key vault was created in. | +| `resourceId` | string | The resource ID of the key vault. | +| `uri` | string | The URI of the key vault. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) +- [Vaults/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/keys) +- [Vaults/Secrets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/secrets) diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e73c70963 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Key Vault Secrets User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource secret 'Microsoft.KeyVault/vaults/secrets@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(secret.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: secret +}] diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/deploy.bicep b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/deploy.bicep new file mode 100644 index 000000000..88ab876bb --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/deploy.bicep @@ -0,0 +1,73 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Required. The name of the secret') +param name string + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Determines whether the object is enabled.') +param attributesEnabled bool = true + +@description('Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible.') +param attributesExp int = -1 + +@description('Optional. Not before date in seconds since 1970-01-01T00:00:00Z.') +param attributesNbf int = -1 + +@description('Optional. The content type of the secret.') +@secure() +param contentType string = '' + +@description('Required. The value of the secret. NOTE: "value" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets.') +@secure() +param value string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +module pid_cuaId './.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource secret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = { + name: name + parent: keyVault + tags: tags + properties: { + contentType: contentType + attributes: { + enabled: attributesEnabled + exp: !(attributesExp == -1) ? attributesExp : null + nbf: !(attributesNbf == -1) ? attributesNbf : null + } + value: value + } +} + +module secret_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: secret.id + } +}] + +@description('The name of the secret.') +output name string = secret.name + +@description('The resource ID of the secret.') +output resourceId string = secret.id + +@description('The name of the resource group the secret was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/readme.md b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/readme.md new file mode 100644 index 000000000..ff4a955c9 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/readme.md @@ -0,0 +1,77 @@ +# Key Vault Secret `[Microsoft.KeyVault/vaults/secrets]` + +This module deploys a key vault secret. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.KeyVault/vaults/secrets` | 2019-09-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `attributesEnabled` | bool | `True` | | Optional. Determines whether the object is enabled. | +| `attributesExp` | int | `-1` | | Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible. | +| `attributesNbf` | int | `-1` | | Optional. Not before date in seconds since 1970-01-01T00:00:00Z. | +| `contentType` | secureString | | | Optional. The content type of the secret. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `keyVaultName` | string | | | Required. The name of the key vault | +| `name` | string | | | Required. The name of the secret | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Resource tags. | +| `value` | secureString | | | Required. The value of the secret. NOTE: "value" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the secret. | +| `resourceGroupName` | string | The name of the resource group the secret was created in. | +| `resourceId` | string | The resource ID of the secret. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Secrets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/secrets) diff --git a/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/version.json b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/secrets/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/carml/1.0.0/Microsoft.KeyVault/vaults/version.json b/carml/1.0.0/Microsoft.KeyVault/vaults/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.KeyVault/vaults/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/carml/1.0.0/Microsoft.Logic/workflows/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Logic/workflows/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Logic/workflows/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Logic/workflows/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Logic/workflows/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..9a4e712fd --- /dev/null +++ b/carml/1.0.0/Microsoft.Logic/workflows/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Sentinel Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4c81013-99ee-4d62-a7ee-b3f1f648599a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource logicApp 'Microsoft.Logic/workflows@2019-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(logicApp.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: logicApp +}] diff --git a/carml/1.0.0/Microsoft.Logic/workflows/.parameters/parameters.json b/carml/1.0.0/Microsoft.Logic/workflows/.parameters/parameters.json new file mode 100644 index 000000000..7ead1ba4b --- /dev/null +++ b/carml/1.0.0/Microsoft.Logic/workflows/.parameters/parameters.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lga-x-001" + }, + "tags": { + "value": {} + }, + "workflowActions": { + "value": { + "HTTP": { + "type": "Http", + "inputs": { + "method": "POST", + "uri": "https://testStringForValidation.com", + "body": { + "HostPoolName": "[HostPoolName]", + "LAWorkspaceName": "[LAWorkspaceName]", + "LimitSecondsToForceLogOffUser": "[LimitSecondsToForceLogOffUser]", + "EndPeakTime": "[EndPeakTime]", + "BeginPeakTime": "[BeginPeakTime]", + "UtcOffset": "[UtcOffset]", + "LogOffMessageBody": "[LogOffMessageBody]", + "LogOffMessageTitle": "[LogOffMessageTitle]", + "MinimumNumberOfRDSH": 1, + "SessionThresholdPerCPU": 1, + "ResourceGroupName": "[ResourceGroupName]" + } + } + } + } + }, + "workflowTriggers": { + "value": { + "Recurrence": { + "recurrence": { + "frequency": "Minute", + "interval": 15 + }, + "type": "Recurrence" + } + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.0/Microsoft.Logic/workflows/deploy.bicep b/carml/1.0.0/Microsoft.Logic/workflows/deploy.bicep new file mode 100644 index 000000000..bf21c125f --- /dev/null +++ b/carml/1.0.0/Microsoft.Logic/workflows/deploy.bicep @@ -0,0 +1,224 @@ +@description('Required. The logic app workflow name.') +param name string + +@description('Optional. The access control configuration for workflow actions.') +param actionsAccessControlConfiguration object = {} + +@description('Optional. The endpoints configuration: Access endpoint and outgoing IP addresses for the connector.') +param connectorEndpointsConfiguration object = {} + +@description('Optional. The access control configuration for accessing workflow run contents.') +param contentsAccessControlConfiguration object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +@description('Optional. Parameters for the definition template.') +param definitionParameters object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The integration account.') +param integrationAccount object = {} + +@description('Optional. The integration service environment.') +param integrationServiceEnvironment object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Sku of Logic App. Only to be set when integrating with ISE.') +param sku object = {} + +@description('Optional. The state. - NotSpecified, Completed, Enabled, Disabled, Deleted, Suspended.') +@allowed([ + 'NotSpecified' + 'Completed' + 'Enabled' + 'Disabled' + 'Deleted' + 'Suspended' +]) +param state string = 'Enabled' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The access control configuration for invoking workflow triggers.') +param triggersAccessControlConfiguration object = {} + +@description('Optional. The definitions for one or more actions to execute at workflow runtime.') +param workflowActions object = {} + +@description('Optional. The endpoints configuration: Access endpoint and outgoing IP addresses for the workflow.') +param workflowEndpointsConfiguration object = {} + +@description('Optional. The access control configuration for workflow management.') +param workflowManagementAccessControlConfiguration object = {} + +@description('Optional. The definitions for the outputs to return from a workflow run.') +param workflowOutputs object = {} + +@description('Optional. The definitions for one or more parameters that pass the values to use at your logic app\'s runtime.') +param workflowParameters object = {} + +@description('Optional. The definitions for one or more static results returned by actions as mock outputs when static results are enabled on those actions. In each action definition, the runtimeConfiguration.staticResult.name attribute references the corresponding definition inside staticResults.') +param workflowStaticResults object = {} + +@description('Optional. The definitions for one or more triggers that instantiate your workflow. You can define more than one trigger, but only with the Workflow Definition Language, not visually through the Logic Apps Designer.') +param workflowTriggers object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'WorkflowRuntime' +]) +param logsToEnable array = [ + 'WorkflowRuntime' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? 'SystemAssigned' : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource logicApp 'Microsoft.Logic/workflows@2019-05-01' = { + name: name + location: location + tags: !empty(tags) ? tags : null + identity: identity + properties: { + state: state + endpointsConfiguration: { + workflow: workflowEndpointsConfiguration + connector: connectorEndpointsConfiguration + } + sku: !empty(sku) ? sku : null + accessControl: { + triggers: !empty(triggersAccessControlConfiguration) ? triggersAccessControlConfiguration : null + contents: !empty(contentsAccessControlConfiguration) ? contentsAccessControlConfiguration : null + actions: !empty(actionsAccessControlConfiguration) ? actionsAccessControlConfiguration : null + workflowManagement: !empty(workflowManagementAccessControlConfiguration) ? workflowManagementAccessControlConfiguration : null + } + integrationAccount: !empty(integrationAccount) ? integrationAccount : null + integrationServiceEnvironment: !empty(integrationServiceEnvironment) ? integrationServiceEnvironment : null + definition: { + '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#' + actions: workflowActions + contentVersion: '1.0.0.0' + outputs: workflowOutputs + parameters: workflowParameters + staticResults: workflowStaticResults + triggers: workflowTriggers + } + parameters: definitionParameters + } +} + +resource logicApp_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${logicApp.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: logicApp +} + +resource logicApp_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${logicApp.name}-diagnosticsetting' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: logicApp +} + +module logicApp_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LogicApp-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: logicApp.id + } +}] + +@description('The name of the logic app') +output name string = logicApp.name + +@description('The resource group the logic app was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the logic app') +output resourceId string = logicApp.id + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(logicApp.identity, 'principalId') ? logicApp.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Logic/workflows/readme.md b/carml/1.0.0/Microsoft.Logic/workflows/readme.md new file mode 100644 index 000000000..59db82062 --- /dev/null +++ b/carml/1.0.0/Microsoft.Logic/workflows/readme.md @@ -0,0 +1,168 @@ +# Logic Apps `[Microsoft.Logic/workflows]` + +This module deploys a Logic App resource. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Logic/workflows` | 2019-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actionsAccessControlConfiguration` | object | `{object}` | | Optional. The access control configuration for workflow actions. | +| `connectorEndpointsConfiguration` | object | `{object}` | | Optional. The endpoints configuration: Access endpoint and outgoing IP addresses for the connector. | +| `contentsAccessControlConfiguration` | object | `{object}` | | Optional. The access control configuration for accessing workflow run contents. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `definitionParameters` | object | `{object}` | | Optional. Parameters for the definition template. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `integrationAccount` | object | `{object}` | | Optional. The integration account. | +| `integrationServiceEnvironment` | object | `{object}` | | Optional. The integration service environment. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[WorkflowRuntime]` | `[WorkflowRuntime]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The logic app workflow name. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `sku` | object | `{object}` | | Optional. Sku of Logic App. Only to be set when integrating with ISE. | +| `state` | string | `Enabled` | `[NotSpecified, Completed, Enabled, Disabled, Deleted, Suspended]` | Optional. The state. - NotSpecified, Completed, Enabled, Disabled, Deleted, Suspended. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `triggersAccessControlConfiguration` | object | `{object}` | | Optional. The access control configuration for invoking workflow triggers. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `workflowActions` | object | `{object}` | | Optional. The definitions for one or more actions to execute at workflow runtime. | +| `workflowEndpointsConfiguration` | object | `{object}` | | Optional. The endpoints configuration: Access endpoint and outgoing IP addresses for the workflow. | +| `workflowManagementAccessControlConfiguration` | object | `{object}` | | Optional. The access control configuration for workflow management. | +| `workflowOutputs` | object | `{object}` | | Optional. The definitions for the outputs to return from a workflow run. | +| `workflowParameters` | object | `{object}` | | Optional. The definitions for one or more parameters that pass the values to use at your logic app's runtime. | +| `workflowStaticResults` | object | `{object}` | | Optional. The definitions for one or more static results returned by actions as mock outputs when static results are enabled on those actions. In each action definition, the runtimeConfiguration.staticResult.name attribute references the corresponding definition inside staticResults. | +| `workflowTriggers` | object | `{object}` | | Optional. The definitions for one or more triggers that instantiate your workflow. You can define more than one trigger, but only with the Workflow Definition Language, not visually through the Logic Apps Designer. | + +### Parameter Usage `AccessControlConfiguration` + +- `actionsAccessControlConfiguration` +- `contentsAccessControlConfiguration` +- `triggersAccessControlConfiguration` +- `workflowManagementAccessControlConfiguration` + +```json +"AccessControlConfiguration": { + "value": { + "allowedCallerIpAddresses": [ + { + "addressRange": "string" + } + ], + "openAuthenticationPolicies": { +"policies": {} + } + } +} +``` + +### Parameter Usage `EndpointsConfiguration` + +- `connectorEndpointsConfiguration` +- `workflowEndpointsConfiguration` + +```json +"EndpointsConfiguration": { + "value": { + "outgoingIpAddresses": [ + { + "address": "string" + } + ], + "accessEndpointIpAddresses": [ + { + "address": "string" + } + ] +} +``` + +### Parameter Usage `workflow*` + +- To use the below parameters, see the following [documentation.](https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-workflow-definition-language) + - `workflowActions` + - `workflowOutputs` + - `workflowParameters` + - `workflowStaticResults` + - `workflowTriggers` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the logic app | +| `resourceGroupName` | string | The resource group the logic app was deployed into | +| `resourceId` | string | The resource ID of the logic app | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workflows](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Logic/2019-05-01/workflows) diff --git a/carml/1.0.0/Microsoft.Logic/workflows/version.json b/carml/1.0.0/Microsoft.Logic/workflows/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Logic/workflows/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/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..82ab478cd --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..1ec6025c2 --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,33 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'AzureML Metrics Writer (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '635dd51f-9968-44d3-b7fb-6d9a6bd613ae') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.MachineLearningServices/workspaces@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: workspace +}] diff --git a/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.parameters/parameters.json b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..82dc8e870 --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-mls-x-001" + }, + "sku": { + "value": "Basic" + }, + "associatedStorageAccountResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "associatedKeyVaultResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "associatedApplicationInsightsResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/deploy.bicep b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/deploy.bicep new file mode 100644 index 000000000..e3be568b3 --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. The name of the machine learning workspace.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Specifies the sku, also referred as \'edition\' of the Azure Machine Learning workspace.') +@allowed([ + 'Basic' + 'Enterprise' +]) +param sku string + +@description('Required. The resource ID of the associated Storage Account.') +param associatedStorageAccountResourceId string + +@description('Required. The resource ID of the associated Key Vault.') +param associatedKeyVaultResourceId string + +@description('Required. The resource ID of the associated Application Insights.') +param associatedApplicationInsightsResourceId string + +@description('Optional. The resource ID of the associated Container Registry.') +param associatedContainerRegistryResourceId string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The flag to signal HBI data in the workspace and reduce diagnostic data collected by the service.') +param hbiWorkspace bool = false + +@description('Optional. The flag to indicate whether to allow public access when behind VNet.') +param allowPublicAccessWhenBehindVnet bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AmlComputeClusterEvent' + 'AmlComputeClusterNodeEvent' + 'AmlComputeJobEvent' + 'AmlComputeCpuGpuUtilization' + 'AmlRunStatusChangedEvent' +]) +param logsToEnable array = [ + 'AmlComputeClusterEvent' + 'AmlComputeClusterNodeEvent' + 'AmlComputeJobEvent' + 'AmlComputeCpuGpuUtilization' + 'AmlRunStatusChangedEvent' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? 'SystemAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource workspace 'Microsoft.MachineLearningServices/workspaces@2021-04-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + tier: sku + } + identity: identity + properties: { + friendlyName: name + storageAccount: associatedStorageAccountResourceId + keyVault: associatedKeyVaultResourceId + applicationInsights: associatedApplicationInsightsResourceId + containerRegistry: ((!(associatedContainerRegistryResourceId == '')) ? associatedContainerRegistryResourceId : null) + hbiWorkspace: hbiWorkspace + allowPublicAccessWhenBehindVnet: allowPublicAccessWhenBehindVnet + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-MLWorkspace-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: workspace.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-MLWorkspace-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The resource ID of the machine learning service') +output resourceId string = workspace.id + +@description('The resource group the machine learning service was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the machine learning service') +output name string = workspace.name + +@description('The principal ID of the system assigned identity.') +output principalId string = systemAssignedIdentity ? workspace.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/readme.md b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/readme.md new file mode 100644 index 000000000..9d6c8348d --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/readme.md @@ -0,0 +1,134 @@ +# Machine Learning Workspaces `[Microsoft.MachineLearningServices/workspaces]` + +This module deploys a Machine Learning Services Workspace. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.MachineLearningServices/workspaces` | 2021-04-01 | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowPublicAccessWhenBehindVnet` | bool | | | Optional. The flag to indicate whether to allow public access when behind VNet. | +| `associatedApplicationInsightsResourceId` | string | | | Required. The resource ID of the associated Application Insights. | +| `associatedContainerRegistryResourceId` | string | | | Optional. The resource ID of the associated Container Registry. | +| `associatedKeyVaultResourceId` | string | | | Required. The resource ID of the associated Key Vault. | +| `associatedStorageAccountResourceId` | string | | | Required. The resource ID of the associated Storage Account. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `hbiWorkspace` | bool | | | Optional. The flag to signal HBI data in the workspace and reduce diagnostic data collected by the service. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[AmlComputeClusterEvent, AmlComputeClusterNodeEvent, AmlComputeJobEvent, AmlComputeCpuGpuUtilization, AmlRunStatusChangedEvent]` | `[AmlComputeClusterEvent, AmlComputeClusterNodeEvent, AmlComputeJobEvent, AmlComputeCpuGpuUtilization, AmlRunStatusChangedEvent]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the machine learning workspace. | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | | `[Basic, Enterprise]` | Required. Specifies the sku, also referred as 'edition' of the Azure Machine Learning workspace. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Resource tags. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the machine learning service | +| `principalId` | string | The principal ID of the system assigned identity. | +| `resourceGroupName` | string | The resource group the machine learning service was deployed into | +| `resourceId` | string | The resource ID of the machine learning service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.MachineLearningServices/2021-04-01/workspaces) diff --git a/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/version.json b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.MachineLearningServices/workspaces/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/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ae2197082 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource userMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(userMsi.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: userMsi +}] diff --git a/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json new file mode 100644 index 000000000..141d57730 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-msi-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep new file mode 100644 index 000000000..216045fe8 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep @@ -0,0 +1,66 @@ +@description('Optional. Name of the User Assigned Identity.') +param name string = guid(resourceGroup().id) + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 userMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: name + location: location + tags: tags +} + +resource userMsi_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${userMsi.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: userMsi +} + +module userMsi_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-UserMSI-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: userMsi.id + } +}] + +@description('The name of the user assigned identity') +output name string = userMsi.name + +@description('The resource ID of the user assigned identity') +output resourceId string = userMsi.id + +@description('The principal ID of the user assigned identity') +output principalId string = userMsi.properties.principalId + +@description('The client ID of the user assigned identity') +output clientId string = userMsi.properties.clientId + +@description('The resource group the user assigned identity was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md new file mode 100644 index 000000000..72a336d18 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md @@ -0,0 +1,76 @@ +# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` + +This module deploys a user assigned identity. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ManagedIdentity/userAssignedIdentities` | 2018-11-30 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | `[guid(resourceGroup().id)]` | | Optional. Name of the User Assigned Identity. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the user assigned identity | +| `principalId` | string | The principal ID of the user assigned identity | +| `resourceGroupName` | string | The resource group the user assigned identity was deployed into | +| `resourceId` | string | The resource ID of the user assigned identity | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Userassignedidentities](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2018-11-30/userAssignedIdentities) diff --git a/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/version.json b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/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/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.bicep/nested_registrationAssignment.bicep b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.bicep/nested_registrationAssignment.bicep new file mode 100644 index 000000000..7bfca49e9 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.bicep/nested_registrationAssignment.bicep @@ -0,0 +1,15 @@ +param registrationDefinitionId string +param registrationAssignmentId string + +resource registrationAssignment 'Microsoft.ManagedServices/registrationAssignments@2019-09-01' = { + name: registrationAssignmentId + properties: { + registrationDefinitionId: registrationDefinitionId + } +} + +@description('The name of the registration assignment') +output name string = registrationAssignment.name + +@description('The resource ID of the registration assignment') +output resourceId string = registrationAssignment.id diff --git a/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.parameters/parameters.json b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.parameters/parameters.json new file mode 100644 index 000000000..8fc6fc1cc --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "Component Validation - Subscription assignment" + }, + "registrationDescription": { + "value": "Managed by Lighthouse" + }, + "managedByTenantId": { + "value": "195ee85d-2f10-4764-8352-a3c99aa772fb" + }, + "authorizations": { + "value": [ + { + "principalId": "e87a249c-b53b-4685-94fe-863af522e4ee", + "principalIdDisplayName": "ResourceModules-Reader", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + }, + { + "principalId": "e2f126a7-136e-443f-b39f-f73ddfd146b1", + "principalIdDisplayName": "ResourceModules-Contributor", + "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "87813317-fb25-4c76-91fe-783af429d109", + "principalIdDisplayName": "ResourceModules-LHManagement", + "roleDefinitionId": "91c1777a-f3dc-4fae-b103-61d183457e46" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.parameters/rg.parameters.json b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.parameters/rg.parameters.json new file mode 100644 index 000000000..5e2141436 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/.parameters/rg.parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "Component Validation - Resource group assignment" + }, + "registrationDescription": { + "value": "Managed by Lighthouse" + }, + "managedByTenantId": { + "value": "195ee85d-2f10-4764-8352-a3c99aa772fb" + }, + "resourceGroupName": { + "value": "validation-rg" + }, + "authorizations": { + "value": [ + { + "principalId": "e87a249c-b53b-4685-94fe-863af522e4ee", + "principalIdDisplayName": "ResourceModules-Reader", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + }, + { + "principalId": "e2f126a7-136e-443f-b39f-f73ddfd146b1", + "principalIdDisplayName": "ResourceModules-Contributor", + "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "87813317-fb25-4c76-91fe-783af429d109", + "principalIdDisplayName": "ResourceModules-LHManagement", + "roleDefinitionId": "91c1777a-f3dc-4fae-b103-61d183457e46" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/deploy.bicep b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/deploy.bicep new file mode 100644 index 000000000..eccdce1f0 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/deploy.bicep @@ -0,0 +1,56 @@ +targetScope = 'subscription' + +@description('Required. Specify a unique name for your offer/registration. i.e \' - - \'') +param name string + +@description('Required. Description of the offer/registration. i.e. \'Managed by \'') +param registrationDescription string + +@description('Required. Specify the tenant ID of the tenant which homes the principals you are delegating permissions to.') +param managedByTenantId string + +@description('Required. Specify an array of objects, containing object of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider\'s Active Directory and the principalIdDisplayName is visible to customers.') +param authorizations array + +@description('Optional. Specify the name of the Resource Group to delegate access to. If not provided, delegation will be done on the targeted subscription.') +param resourceGroupName string = '' + +var registrationId = empty(resourceGroupName) ? guid(managedByTenantId, subscription().tenantId, subscription().subscriptionId) : guid(managedByTenantId, subscription().tenantId, subscription().subscriptionId, resourceGroupName) + +resource registrationDefinition 'Microsoft.ManagedServices/registrationDefinitions@2019-09-01' = { + name: registrationId + properties: { + registrationDefinitionName: name + description: registrationDescription + managedByTenantId: managedByTenantId + authorizations: authorizations + } +} + +resource registrationAssignment_sub 'Microsoft.ManagedServices/registrationAssignments@2019-09-01' = if (empty(resourceGroupName)) { + name: registrationId + properties: { + registrationDefinitionId: registrationDefinition.id + } +} + +module registrationAssignment_rg '.bicep/nested_registrationAssignment.bicep' = if (!empty(resourceGroupName)) { + name: '${uniqueString(deployment().name)}-RegDef-RegAssignment' + scope: resourceGroup(resourceGroupName) + params: { + registrationDefinitionId: registrationDefinition.id + registrationAssignmentId: registrationId + } +} + +@description('The name of the registration definition') +output name string = registrationDefinition.name + +@description('The resource ID of the registration definition') +output resourceId string = registrationDefinition.id + +@description('The subscription the registration definition was deployed into') +output subscriptionName string = subscription().displayName + +@description('The registration assignment resource ID') +output assignmentResourceId string = empty(resourceGroupName) ? registrationAssignment_sub.id : registrationAssignment_rg.outputs.resourceId diff --git a/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/readme.md b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/readme.md new file mode 100644 index 000000000..54e148c0f --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/readme.md @@ -0,0 +1,121 @@ +# Registration Definitions `[Microsoft.ManagedServices/registrationDefinitions]` + +This module deploys `registrationDefinitions` and `registrationAssignments` (often refered to as 'Lighthouse' or 'resource delegation') +on subscription or resource group scopes. This type of delegation is very similar to role assignments but here the principal that is +assigned a role is in a remote/managing Azure Active Directory tenant. The templates are run towards the tenant where +the Azure resources you want to delegate access to are, providing 'authorizations' (aka. access delegation) to principals in a +remote/managing tenant. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ManagedServices/registrationAssignments` | 2019-09-01 | +| `Microsoft.ManagedServices/registrationDefinitions` | 2019-09-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizations` | array | | | Required. Specify an array of objects, containing object of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider's Active Directory and the principalIdDisplayName is visible to customers. | +| `managedByTenantId` | string | | | Required. Specify the tenant ID of the tenant which homes the principals you are delegating permissions to. | +| `name` | string | | | Required. Specify a unique name for your offer/registration. i.e ' - - ' | +| `registrationDescription` | string | | | Required. Description of the offer/registration. i.e. 'Managed by ' | +| `resourceGroupName` | string | | | Optional. Specify the name of the Resource Group to delegate access to. If not provided, delegation will be done on the targeted subscription. | + +### Parameter Usage: `authorizations` + +| Parameter Name | Type | Default Value | Possible values | Description | +| :----------------------- | :----- | :------------ | :-------------- | :------------------------------------------------------------------------------------------ | +| `principalId` | string | | GUID | Required. The object ID of the principal in the managing tenant to delegate permissions to. | +| `principalIdDisplayName` | string | `principalId` | | Optional. A display name of the principal that is delegated permissions to. | +| `roleDefinitionId` | string | | GUID | Required. The role definition ID to delegate to the principal in the managing tenant. | + +```json +"authorizations": { + "value": [ + // Delegates 'Reader' to a group in managing tenant (managedByTenantId) + { + "principalId": "9d949eef-00d5-45d9-8586-56be91a13398", + "principalIdDisplayName": "Reader-Group", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + }, + // Delegates 'Contributor' to a group in managing tenant (managedByTenantId) + { + "principalId": "06eb144f-1a10-4935-881b-757efd1d0b58", + "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + // Delegates 'Managed Services Registration assignment Delete Role' to a group in managing tenant (managedByTenantId) + { + "principalId": "9cd792b0-dc7c-4551-84f8-dd87388030fb", + "principalIdDisplayName": "LighthouseManagement-Group", + "roleDefinitionId": "91c1777a-f3dc-4fae-b103-61d183457e46" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the registration definition | +| `assignmentResourceId` | string | The registration assignment resource ID | +| `resourceId` | string | The resource ID of the registration definition | +| `subscriptionName` | string | The subscription the registration definition was deployed into | + +## Considerations + +This module can be deployed both at subscription and resource group level: + +- To deploy the module at resource group level, provide a valid name of an existing Resource Group in the `resourceGroupName` parameter. +- To deploy the module at the subscription level, leave the `resourceGroupName` parameter empty. + +### Permissions required to create delegations + +This deployment must be done by a non-guest account in the customer's tenant which has a role with the `Microsoft.Authorization/roleAssignments/write` permission, +such as [`Owner`](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#owner) for the subscription being onboarded (or which contains the resource groups that are being onboarded). + +If the subscription was created through the Cloud Solution Provider (CSP) program, any user who has the AdminAgent role in your service provider tenant can perform the deployment. + +**More info on this topic:** + +- [Deploy the Azure Resource Manager templates - Onboard a customer to Azure Lighthouse | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer#deploy-the-azure-resource-manager-templates) + +### Permissions required to remove delegations + +#### From customer side + +Users in the customer's tenant who have a role with the `Microsoft.Authorization/roleAssignments/write` permission, such as +[`Owner`](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#owner) can remove service provider +access to that subscription (or to resource groups in that subscription). To do so, the user can go to the Service providers +page of the Azure portal and delete the delegation. + +#### From managing tenant side + +Users in a managing tenant can remove access to delegated resources if they were granted the +[`Managed Services Registration Assignment Delete Role`](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#managed-services-registration-assignment-delete-role) +for the customer's resources. If this role was not assigned to any service provider users, the delegation can **only** be +removed by a user in the customer's tenant. + +**More info on this topic:** + +- [Service providers - Remove access to a delegation | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/how-to/remove-delegation#service-providers) + +### Limitations with Lighthouse and resource delegation + +There are a couple of limitations that you should be aware of with Lighthouse: + +- Only allows resource delegation within Azure Resource Manager. Excludes Azure Active Directory, Microsoft 365 and Dynamics 365. +- Only supports delegation of control plane permissions. Excludes data plane access. +- Only supports subscription and resource group scopes. Excludes tenant and management group delegations. +- Only supports built-in roles, with the exception of `Owner`. Excludes the use of custom roles. + +**More info on this topic:** + +- [Current limitations - Cross-tenant management experiences | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/concepts/cross-tenant-management-experience#current-limitations) +- [Troubleshooting - Onboard a customer to Azure Lighthouse | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer#troubleshooting) + +## Template references + +- [Define resources with Bicep and ARM templates](https://docs.microsoft.com/en-us/azure/templates) diff --git a/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/version.json b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ManagedServices/registrationDefinitions/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/carml/1.0.0/Microsoft.Management/managementGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Management/managementGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..a1b14cfd9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Management/managementGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,297 @@ +targetScope = 'managementGroup' + +param principalIds array +param roleDefinitionIdOrName string +param resourceName string + +var builtInRoleNames = { + 'AcrPush': '/providers/Microsoft.Authorization/roleDefinitions/8311e382-0749-4cb8-b61a-304f252e45ec' + 'API Management Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/312a565d-c81f-4fd8-895a-4e21e48d571c' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(resourceName, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } +}] diff --git a/carml/1.0.0/Microsoft.Management/managementGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Management/managementGroups/.parameters/parameters.json new file mode 100644 index 000000000..2ecb3b947 --- /dev/null +++ b/carml/1.0.0/Microsoft.Management/managementGroups/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "testMG" + }, + "displayName": { + "value": "Test MG" + }, + "parentId": { + "value": "<>" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Management/managementGroups/deploy.bicep b/carml/1.0.0/Microsoft.Management/managementGroups/deploy.bicep new file mode 100644 index 000000000..b85783a47 --- /dev/null +++ b/carml/1.0.0/Microsoft.Management/managementGroups/deploy.bicep @@ -0,0 +1,42 @@ +targetScope = 'managementGroup' + +@description('Required. The group ID of the Management group') +param name string + +@description('Optional. The friendly name of the management group. If no value is passed then this field will be set to the group ID.') +param displayName string = '' + +@description('Optional. The management group parent ID. Defaults to current scope.') +param parentId string = '' + +@description('Optional. Array of role assignment objects to define RBAC on this resource.') +param roleAssignments array = [] + +resource managementGroup 'Microsoft.Management/managementGroups@2021-04-01' = { + name: name + scope: tenant() + properties: { + displayName: displayName + details: !empty(parentId) ? { + parent: { + id: '/providers/Microsoft.Management/managementGroups/${parentId}' + } + } : null + } +} + +module managementGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name)}-ManagementGroup-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceName: managementGroup.name + } + scope: managementGroup +}] + +@description('The name of the management group') +output name string = managementGroup.name + +@description('The resource ID of the management group') +output resourceId string = managementGroup.id diff --git a/carml/1.0.0/Microsoft.Management/managementGroups/readme.md b/carml/1.0.0/Microsoft.Management/managementGroups/readme.md new file mode 100644 index 000000000..66d0c227a --- /dev/null +++ b/carml/1.0.0/Microsoft.Management/managementGroups/readme.md @@ -0,0 +1,76 @@ +# Management Groups `[Microsoft.Management/managementGroups]` + +This template will prepare the management group structure based on the provided parameter. + +This module has some known **limitations**: + +- It's not possible to change the display name of the root management group (the one that has the tenant GUID as ID) +- It can't manage the Root (/) management group + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Management/managementGroups` | 2021-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `displayName` | string | | | Optional. The friendly name of the management group. If no value is passed then this field will be set to the group ID. | +| `name` | string | | | Required. The group ID of the Management group | +| `parentId` | string | | | Optional. The management group parent ID. Defaults to current scope. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects to define RBAC on this resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the management group | +| `resourceId` | string | The resource ID of the management group | + +## Considerations + +This template is using a **Tenant level deployment**, meaning the user/principal deploying it needs to have the [proper access](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/deploy-to-tenant#required-access) + +If owner access is excessive, the following rights roles will grant enough rights: + +- **Automation Job Operator** at **tenant** level (scope '/') +- **Management Group Contributor** at the top management group that needs to be managed + +Consider using the following script: + +```powershell +$PrincipalID = "" +$TopMGID = "" +New-AzRoleAssignment -ObjectId $PrincipalID -Scope "/" -RoleDefinitionName "Automation Job Operator" +New-AzRoleAssignment -ObjectId $PrincipalID -Scope "/providers/Microsoft.Management/managementGroups/$TopMGID" -RoleDefinitionName "Management Group Contributor" +``` + +## Template references + +- [Managementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Management/2021-04-01/managementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Management/managementGroups/version.json b/carml/1.0.0/Microsoft.Management/managementGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Management/managementGroups/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/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..99adf87f9 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(netAppAccount.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: netAppAccount +}] diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..029d5ebc0 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-anf-min-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/nfs3.parameters.json b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/nfs3.parameters.json new file mode 100644 index 000000000..1e5a91b39 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/nfs3.parameters.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-anf-nfs3-001" + }, + "capacityPools": { + "value": [ + { + "name": "<>-az-anfcp-x-001", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "name": "anf3-vol01-nfsv3", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv3" + ], + "exportPolicyRules": [ + { + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true, + "nfsv3": true, + "nfsv41": false, + "allowedClients": "0.0.0.0/0" + } + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "anf3-vol02-nfsv3", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv3" + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004" + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-anfcp-x-002", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + } + } +} diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/nfs41.parameters.json b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/nfs41.parameters.json new file mode 100644 index 000000000..2f961c144 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/.parameters/nfs41.parameters.json @@ -0,0 +1,106 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-anf-nfs41-001" + }, + "capacityPools": { + "value": [ + { + "name": "<>-az-anfcp-x-001", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "name": "anf4-vol01-nfsv41", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv4.1" + ], + "exportPolicyRules": [ + { + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true, + "nfsv3": false, + "nfsv41": true, + "allowedClients": "0.0.0.0/0" + } + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "anf4-vol02-nfsv41", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv4.1" + ], + "exportPolicyRules": [ + { + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true, + "nfsv3": false, + "nfsv41": true, + "allowedClients": "0.0.0.0/0" + } + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004" + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-anfcp-x-002", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + } + } +} diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..cc35a1f3d --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource capacityPool 'Microsoft.NetApp/netAppAccounts/capacityPools@2021-04-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(capacityPool.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: capacityPool +}] diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/deploy.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/deploy.bicep new file mode 100644 index 000000000..46672a969 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/deploy.bicep @@ -0,0 +1,100 @@ +@description('Required. The name of the NetApp account.') +param netAppAccountName string + +@description('Required. The name of the capacity pool.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. The pool service level.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104).') +param size int + +@description('Optional. The qos type of the pool.') +@allowed([ + 'Auto' + 'Manual' +]) +param qosType string = 'Auto' + +@description('Optional. List of volumnes to create in the capacity pool.') +param volumes array = [] + +@description('Optional. If enabled (true) the pool can contain cool Access enabled volumes.') +param coolAccess bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' existing = { + name: netAppAccountName +} + +resource capacityPool 'Microsoft.NetApp/netAppAccounts/capacityPools@2021-06-01' = { + name: name + parent: netAppAccount + location: location + tags: tags + properties: { + serviceLevel: serviceLevel + size: size + qosType: qosType + coolAccess: coolAccess + } +} + +@batchSize(1) +module capacityPool_volumes 'volumes/deploy.bicep' = [for (volume, index) in volumes: { + name: '${deployment().name}-Vol-${index}' + params: { + netAppAccountName: netAppAccount.name + capacityPoolName: capacityPool.name + name: volume.name + location: location + serviceLevel: serviceLevel + creationToken: contains(volume, 'creationToken') ? volume.creationToken : volume.name + usageThreshold: volume.usageThreshold + protocolTypes: contains(volume, 'protocolTypes') ? volume.protocolTypes : [] + subnetResourceId: volume.subnetResourceId + exportPolicyRules: contains(volume, 'exportPolicyRules') ? volume.exportPolicyRules : [] + roleAssignments: contains(volume, 'roleAssignments') ? volume.roleAssignments : [] + } +}] + +module capacityPool_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: capacityPool.id + } +}] + +@description('The name of the Capacity Pool.') +output name string = capacityPool.name + +@description('The resource ID of the Capacity Pool.') +output resourceId string = capacityPool.id + +@description('The name of the Resource Group the Capacity Pool was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/readme.md b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/readme.md new file mode 100644 index 000000000..ed5ccd45e --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/readme.md @@ -0,0 +1,80 @@ +# Azure NetApp Files Capacity Pools `[Microsoft.NetApp/netAppAccounts/capacityPools]` + +This template deploys capacity pools in an Azure NetApp Files. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | 2021-06-01 | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `coolAccess` | bool | | | Optional. If enabled (true) the pool can contain cool Access enabled volumes. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location of the pool volume. | +| `name` | string | | | Required. The name of the capacity pool. | +| `netAppAccountName` | string | | | Required. The name of the NetApp account. | +| `qosType` | string | `Auto` | `[Auto, Manual]` | Optional. The qos type of the pool. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serviceLevel` | string | `Standard` | `[Premium, Standard, StandardZRS, Ultra]` | Optional. The pool service level. | +| `size` | int | | | Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). | +| `tags` | object | `{object}` | | Optional. Tags for all resources. | +| `volumes` | _[volumes](volumes/readme.md)_ array | `[]` | | Optional. List of volumnes to create in the capacity pool. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Capacity Pool. | +| `resourceGroupName` | string | The name of the Resource Group the Capacity Pool was created in. | +| `resourceId` | string | The resource ID of the Capacity Pool. | + +## Template references + +- [Netappaccounts/Capacitypools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools) +- [Netappaccounts/Capacitypools/Volumes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools/volumes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/version.json b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/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/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b7caad5b4 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2021-04-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(volume.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: volume +}] diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/deploy.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/deploy.bicep new file mode 100644 index 000000000..05778776e --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/deploy.bicep @@ -0,0 +1,88 @@ +@description('Required. The name of the NetApp account.') +param netAppAccountName string + +@description('Required. The name of the capacity pool.') +param capacityPoolName string + +@description('Required. The name of the pool volume.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. The pool service level. Must match the one of the parent capacity pool.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription.') +param creationToken string = name + +@description('Required. Maximum storage quota allowed for a file system in bytes.') +param usageThreshold int + +@description('Optional. Set of protocol types.') +param protocolTypes array = [] + +@description('Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes.') +param subnetResourceId string + +@description('Optional. Export policy rules.') +param exportPolicyRules array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' existing = { + name: netAppAccountName + + resource capacityPool 'capacityPools@2021-06-01' existing = { + name: capacityPoolName + } +} + +resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2021-06-01' = { + name: name + parent: netAppAccount::capacityPool + location: location + properties: { + serviceLevel: serviceLevel + creationToken: creationToken + usageThreshold: usageThreshold + protocolTypes: protocolTypes + subnetId: subnetResourceId + exportPolicy: !empty(exportPolicyRules) ? { + rules: exportPolicyRules + } : null + } +} + +module volume_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: volume.id + } +}] + +@description('The name of the Volume.') +output name string = volume.name + +@description('The Resource ID of the Volume.') +output resourceId string = volume.id + +@description('The name of the Resource Group the Volume was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/readme.md b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/readme.md new file mode 100644 index 000000000..003d14360 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/readme.md @@ -0,0 +1,62 @@ +# Azure NetApp Files Capacity Pool Volumes `[Microsoft.NetApp/netAppAccounts/capacityPools/volumes]` + +This template deploys volumes in a capacity pool of an Azure NetApp files. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `capacityPoolName` | string | | | Required. The name of the capacity pool. | +| `creationToken` | string | `[parameters('name')]` | | Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `exportPolicyRules` | array | `[]` | | Optional. Export policy rules. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location of the pool volume. | +| `name` | string | | | Required. The name of the pool volume. | +| `netAppAccountName` | string | | | Required. The name of the NetApp account. | +| `protocolTypes` | array | `[]` | | Optional. Set of protocol types. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serviceLevel` | string | `Standard` | `[Premium, Standard, StandardZRS, Ultra]` | Optional. The pool service level. Must match the one of the parent capacity pool. | +| `subnetResourceId` | string | | | Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. | +| `usageThreshold` | int | | | Required. Maximum storage quota allowed for a file system in bytes. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Volume. | +| `resourceGroupName` | string | The name of the Resource Group the Volume was created in. | +| `resourceId` | string | The Resource ID of the Volume. | + +## Template references + +- [Netappaccounts/Capacitypools/Volumes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools/volumes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/version.json b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/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/carml/1.0.0/Microsoft.NetApp/netAppAccounts/deploy.bicep b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/deploy.bicep new file mode 100644 index 000000000..e54dd923c --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/deploy.bicep @@ -0,0 +1,112 @@ +@description('Required. The name of the NetApp account.') +param name string + +@description('Optional. Fully Qualified Active Directory DNS Domain Name (e.g. \'contoso.com\')') +param domainName string = '' + +@description('Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain.') +param domainJoinUser string = '' + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param domainJoinPassword string = '' + +@description('Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. \'OU=SecondLevel,OU=FirstLevel\').') +param domainJoinOU string = '' + +@description('Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed.') +param dnsServers string = '' + +@description('Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes') +param smbServerNamePrefix string = '' + +@description('Optional. Capacity pools to create.') +param capacityPools array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var activeDirectoryConnectionProperties = [ + { + username: !empty(domainName) ? domainJoinUser : null + password: !empty(domainName) ? domainJoinPassword : null + domain: !empty(domainName) ? domainName : null + dns: !empty(domainName) ? dnsServers : null + smbServerName: !empty(domainName) ? smbServerNamePrefix : null + organizationalUnit: !empty(domainJoinOU) ? domainJoinOU : null + } +] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' = { + name: name + tags: tags + location: location + properties: { + activeDirectories: !empty(domainName) ? activeDirectoryConnectionProperties : null + } +} + +resource netAppAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${netAppAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: netAppAccount +} + +module netAppAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ANFAccount-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: netAppAccount.id + } +}] + +@batchSize(1) +module netAppAccount_capacityPools 'capacityPools/deploy.bicep' = [for (capacityPool, index) in capacityPools: { + name: '${uniqueString(deployment().name, location)}-ANFAccount-CapPool-${index}' + params: { + netAppAccountName: netAppAccount.name + name: capacityPool.name + location: location + size: capacityPool.size + serviceLevel: contains(capacityPool, 'serviceLevel') ? capacityPool.serviceLevel : 'Standard' + qosType: contains(capacityPool, 'qosType') ? capacityPool.qosType : 'Auto' + volumes: contains(capacityPool, 'volumes') ? capacityPool.volumes : [] + coolAccess: contains(capacityPool, 'coolAccess') ? capacityPool.coolAccess : false + roleAssignments: contains(capacityPool, 'roleAssignments') ? capacityPool.roleAssignments : [] + } +}] + +@description('The name of the NetApp account.') +output name string = netAppAccount.name + +@description('The Resource ID of the NetApp account.') +output resourceId string = netAppAccount.id + +@description('The name of the Resource Group the NetApp account was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/readme.md b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/readme.md new file mode 100644 index 000000000..59cbc245f --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/readme.md @@ -0,0 +1,86 @@ +# Azure NetApp Files `[Microsoft.NetApp/netAppAccounts]` + +This template deploys Azure NetApp Files. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.NetApp/netAppAccounts` | 2021-04-01 | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | 2021-06-01 | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `capacityPools` | _[capacityPools](capacityPools/readme.md)_ array | `[]` | | Optional. Capacity pools to create. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `dnsServers` | string | | | Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed. | +| `domainJoinOU` | string | | | Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel'). | +| `domainJoinPassword` | secureString | | | Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `domainJoinUser` | string | | | Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. | +| `domainName` | string | | | Optional. Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com') | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the NetApp account. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `smbServerNamePrefix` | string | | | Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes | +| `tags` | object | `{object}` | | Optional. Tags for all resources. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NetApp account. | +| `resourceGroupName` | string | The name of the Resource Group the NetApp account was created in. | +| `resourceId` | string | The Resource ID of the NetApp account. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Netappaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-04-01/netAppAccounts) +- [Netappaccounts/Capacitypools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools) +- [Netappaccounts/Capacitypools/Volumes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools/volumes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.NetApp/netAppAccounts/version.json b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.NetApp/netAppAccounts/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/carml/1.0.0/Microsoft.Network/applicationGateways/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/applicationGateways/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationGateways/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..fd2516943 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource applicationGateway 'Microsoft.Network/applicationGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(applicationGateway.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: applicationGateway +}] diff --git a/carml/1.0.0/Microsoft.Network/applicationGateways/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/applicationGateways/.parameters/parameters.json new file mode 100644 index 000000000..e0a8603a8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationGateways/.parameters/parameters.json @@ -0,0 +1,364 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apgw-x-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "webApplicationFirewallConfiguration": { + "value": { + "enabled": true, + "firewallMode": "Detection", + "ruleSetType": "OWASP", + "ruleSetVersion": "3.0", + "disabledRuleGroups": [], + "requestBodyCheck": true, + "maxRequestBodySizeInKb": 128, + "fileUploadLimitInMb": 100 + } + }, + "enableHttp2": { + "value": true + }, + "backendAddressPools": { + "value": [ + { + "name": "appServiceBackendPool", + "properties": { + "backendAddresses": [ + { + "fqdn": "aghapp.azurewebsites.net" + } + ] + } + }, + { + "name": "privateVmBackendPool", + "properties": { + "backendAddresses": [ + { + "ipAddress": "10.0.0.4" + } + ] + } + } + ] + }, + "backendHttpSettingsCollection": { + "value": [ + { + "name": "appServiceBackendHttpsSetting", + "properties": { + "port": 443, + "protocol": "Https", + "cookieBasedAffinity": "Disabled", + "pickHostNameFromBackendAddress": true, + "requestTimeout": 30 + } + }, + { + "name": "privateVmHttpSetting", + "properties": { + "port": 80, + "protocol": "Http", + "cookieBasedAffinity": "Disabled", + "pickHostNameFromBackendAddress": false, + "requestTimeout": 30, + "probe": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/probes/privateVmHttpSettingProbe" + } + } + } + ] + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "private", + "properties": { + "privateIPAddress": "10.0.8.6", + "privateIPAllocationMethod": "Static", + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-007" + } + } + }, + { + "name": "public", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-apgw" + } + } + } + ] + }, + "frontendPorts": { + "value": [ + { + "name": "port443", + "properties": { + "port": 443 + } + }, + { + "name": "port4433", + "properties": { + "port": 4433 + } + }, + { + "name": "port80", + "properties": { + "port": 80 + } + }, + { + "name": "port8080", + "properties": { + "port": 8080 + } + } + ] + }, + "httpListeners": { + "value": [ + { + "name": "public443", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/public" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port443" + }, + "sslCertificate": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/sslCertificates/<>-az-apgw-x-001-ssl-certificate" + }, + "protocol": "https", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "private4433", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/private" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port4433" + }, + "sslCertificate": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/sslCertificates/<>-az-apgw-x-001-ssl-certificate" + }, + "protocol": "https", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "httpRedirect80", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/public" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port80" + }, + "protocol": "Http", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "httpRedirect8080", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/private" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port8080" + }, + "protocol": "Http", + "hostNames": [], + "requireServerNameIndication": false + } + } + ] + }, + "gatewayIPConfigurations": { + "value": [ + { + "name": "apw-ip-configuration", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-007" + } + } + } + ] + }, + "probes": { + "value": [ + { + "name": "privateVmHttpSettingProbe", + "properties": { + "protocol": "Http", + "host": "10.0.0.4", + "path": "/", + "interval": 60, + "timeout": 15, + "unhealthyThreshold": 5, + "pickHostNameFromBackendHttpSettings": false, + "minServers": 3, + "match": { + "statusCodes": [ + "200", + "401" + ] + } + } + } + ] + }, + "redirectConfigurations": { + "value": [ + { + "name": "httpRedirect80", + "properties": { + "redirectType": "Permanent", + "targetListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/public443" + }, + "includePath": true, + "includeQueryString": true, + "requestRoutingRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/requestRoutingRules/httpRedirect80-public443" + } + ] + } + }, + { + "name": "httpRedirect8080", + "properties": { + "redirectType": "Permanent", + "targetListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/private4433" + }, + "includePath": true, + "includeQueryString": true, + "requestRoutingRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/requestRoutingRules/httpRedirect8080-private4433" + } + ] + } + } + ] + }, + "requestRoutingRules": { + "value": [ + { + "name": "public443-appServiceBackendHttpsSetting-appServiceBackendHttpsSetting", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/public443" + }, + "backendAddressPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendAddressPools/appServiceBackendPool" + }, + "backendHttpSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendHttpSettingsCollection/appServiceBackendHttpsSetting" + } + } + }, + { + "name": "private4433-privateVmHttpSetting-privateVmHttpSetting", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/private4433" + }, + "backendAddressPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendAddressPools/privateVmBackendPool" + }, + "backendHttpSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendHttpSettingsCollection/privateVmHttpSetting" + } + } + }, + { + "name": "httpRedirect80-public443", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/httpRedirect80" + }, + "redirectConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/redirectConfigurations/httpRedirect80" + } + } + }, + { + "name": "httpRedirect8080-private4433", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/httpRedirect8080" + }, + "redirectConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/redirectConfigurations/httpRedirect8080" + } + } + } + ] + }, + "sku": { + "value": "WAF_v2" + }, + "sslCertificates": { + "value": [ + { + "name": "<>-az-apgw-x-001-ssl-certificate", + "properties": { + "keyVaultSecretId": "https://adp-<>-az-kv-x-001.vault.azure.net/secrets/applicationGatewaySslCertificate02/40b9b1a7a69e48cfa1e36f24b97b8799" + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/applicationGateways/deploy.bicep b/carml/1.0.0/Microsoft.Network/applicationGateways/deploy.bicep new file mode 100644 index 000000000..b8c7ca293 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationGateways/deploy.bicep @@ -0,0 +1,351 @@ +@description('Required. Name of the Application Gateway.') +@maxLength(24) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Authentication certificates of the application gateway resource.') +param authenticationCertificates array = [] + +@description('Optional. Upper bound on number of Application Gateway capacity.') +param autoscaleMaxCapacity int = -1 + +@description('Optional. Lower bound on number of Application Gateway capacity.') +param autoscaleMinCapacity int = -1 + +@description('Optional. Backend address pool of the application gateway resource.') +param backendAddressPools array = [] + +@description('Optional. Backend http settings of the application gateway resource.') +param backendHttpSettingsCollection array = [] + +@description('Optional. Custom error configurations of the application gateway resource.') +param customErrorConfigurations array = [] + +@description('Optional. Whether FIPS is enabled on the application gateway resource.') +param enableFips bool = false + +@description('Optional. Whether HTTP2 is enabled on the application gateway resource.') +param enableHttp2 bool = false + +@description('Optional. The resource Id of an associated firewall policy.') +param firewallPolicyId string = '' + +@description('Optional. Frontend IP addresses of the application gateway resource.') +param frontendIPConfigurations array = [] + +@description('Optional. Frontend ports of the application gateway resource.') +param frontendPorts array = [] + +@description('Optional. Subnets of the application gateway resource.') +param gatewayIPConfigurations array = [] + +@description('Optional. Enable request buffering.') +param enableRequestBuffering bool = false + +@description('Optional. Enable response buffering.') +param enableResponseBuffering bool = false + +@description('Optional. Http listeners of the application gateway resource.') +param httpListeners array = [] + +@description('Optional. Load distribution policies of the application gateway resource.') +param loadDistributionPolicies array = [] + +@description('Optional. PrivateLink configurations on application gateway.') +param privateLinkConfigurations array = [] + +@description('Optional. Probes of the application gateway resource.') +param probes array = [] + +@description('Optional. Redirect configurations of the application gateway resource.') +param redirectConfigurations array = [] + +@description('Optional. Request routing rules of the application gateway resource.') +param requestRoutingRules array = [] + +@description('Optional. Rewrite rules for the application gateway resource. ') +param rewriteRuleSets array = [] + +@description('Optional. The name of the SKU for the Application Gateway.') +@allowed([ + 'Standard_Small' + 'Standard_Medium' + 'Standard_Large' + 'WAF_Medium' + 'WAF_Large' + 'Standard_v2' + 'WAF_v2' +]) +param sku string = 'WAF_Medium' + +@description('Optional. The number of Application instances to be configured.') +@minValue(1) +@maxValue(10) +param capacity int = 2 + +@description('Optional. SSL certificates of the application gateway resource.') +param sslCertificates array = [] + +@description('Optional. Ssl cipher suites to be enabled in the specified order to application gateway.') +@allowed([ + 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256' + 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256' + 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA' + 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA' + 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA' + 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256' + 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256' + 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA' + 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384' + 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA' + 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256' + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA' + 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_RSA_WITH_3DES_EDE_CBC_SHA' + 'TLS_RSA_WITH_AES_128_CBC_SHA' + 'TLS_RSA_WITH_AES_128_CBC_SHA256' + 'TLS_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_RSA_WITH_AES_256_CBC_SHA' + 'TLS_RSA_WITH_AES_256_CBC_SHA256' + 'TLS_RSA_WITH_AES_256_GCM_SHA384' +]) +param sslPolicyCipherSuites array = [ + 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' +] + +@description('Optional. Ssl protocol enums.') +@allowed([ + 'TLSv1_0' + 'TLSv1_1' + 'TLSv1_2' +]) +param sslPolicyMinProtocolVersion string = 'TLSv1_2' + +@description('Optional. Ssl predefined policy name enums.') +@allowed([ + 'AppGwSslPolicy20150501' + 'AppGwSslPolicy20170401' + 'AppGwSslPolicy20170401S' + '' +]) +param sslPolicyName string = '' + +@description('Optional. Type of Ssl Policy.') +@allowed([ + 'Custom' + 'Predefined' +]) +param sslPolicyType string = 'Custom' + +@description('Optional. SSL profiles of the application gateway resource.') +param sslProfiles array = [] + +@description('Optional. Trusted client certificates of the application gateway resource.') +param trustedClientCertificates array = [] + +@description('Optional. Trusted Root certificates of the application gateway resource.') +param trustedRootCertificates array = [] + +@description('Optional. URL path map of the application gateway resource.') +param urlPathMaps array = [] + +@description('Optional. Application gateway web application firewall configuration.') +param webApplicationFirewallConfiguration object = {} + +@description('Optional. A list of availability zones denoting where the resource needs to come from.') +param zones array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ApplicationGatewayAccessLog' + 'ApplicationGatewayPerformanceLog' + 'ApplicationGatewayFirewallLog' +]) +param logsToEnable array = [ + 'ApplicationGatewayAccessLog' + 'ApplicationGatewayPerformanceLog' + 'ApplicationGatewayFirewallLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@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 applicationGateway 'Microsoft.Network/applicationGateways@2021-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: union({ + authenticationCertificates: authenticationCertificates + autoscaleConfiguration: autoscaleMaxCapacity > 0 && autoscaleMinCapacity > 0 ? { + maxCapacity: autoscaleMaxCapacity + minCapacity: autoscaleMinCapacity + } : null + backendAddressPools: backendAddressPools + backendHttpSettingsCollection: backendHttpSettingsCollection + customErrorConfigurations: customErrorConfigurations + enableHttp2: enableHttp2 + firewallPolicy: !empty(firewallPolicyId) ? { + id: firewallPolicyId + } : null + forceFirewallPolicyAssociation: !empty(firewallPolicyId) + frontendIPConfigurations: frontendIPConfigurations + frontendPorts: frontendPorts + gatewayIPConfigurations: gatewayIPConfigurations + globalConfiguration: { + enableRequestBuffering: enableRequestBuffering + enableResponseBuffering: enableResponseBuffering + } + httpListeners: httpListeners + loadDistributionPolicies: loadDistributionPolicies + privateLinkConfigurations: privateLinkConfigurations + probes: probes + redirectConfigurations: redirectConfigurations + requestRoutingRules: requestRoutingRules + rewriteRuleSets: rewriteRuleSets + sku: { + name: sku + tier: endsWith(sku, 'v2') ? sku : substring(sku, 0, indexOf(sku, '_')) + capacity: autoscaleMaxCapacity > 0 && autoscaleMinCapacity > 0 ? null : capacity + } + sslCertificates: sslCertificates + sslPolicy: { + cipherSuites: sslPolicyCipherSuites + minProtocolVersion: sslPolicyMinProtocolVersion + policyName: empty(sslPolicyName) ? null : sslPolicyName + policyType: sslPolicyType + } + sslProfiles: sslProfiles + trustedClientCertificates: trustedClientCertificates + trustedRootCertificates: trustedRootCertificates + urlPathMaps: urlPathMaps + webApplicationFirewallConfiguration: webApplicationFirewallConfiguration + }, (enableFips ? { + enableFips: enableFips + } : {}), {}) + zones: zones +} + +resource applicationGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${applicationGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: applicationGateway +} + +resource applicationGateway_diagnosticSettingName 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${applicationGateway.name}-diagnosticSettings' + properties: { + storageAccountId: empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId + workspaceId: empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId + eventHubAuthorizationRuleId: empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId + eventHubName: empty(diagnosticEventHubName) ? null : diagnosticEventHubName + metrics: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsMetrics + logs: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsLogs + } + scope: applicationGateway +} + +module applicationGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGateway-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: applicationGateway.id + } +}] + +@description('The name of the application gateway') +output name string = applicationGateway.name + +@description('The resource ID of the application gateway') +output resourceId string = applicationGateway.id + +@description('The resource group the application gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/applicationGateways/readme.md b/carml/1.0.0/Microsoft.Network/applicationGateways/readme.md new file mode 100644 index 000000000..b8b279b20 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationGateways/readme.md @@ -0,0 +1,669 @@ +# Network Application Gateways `[Microsoft.Network/applicationGateways]` + +This module deploys Network ApplicationGateways. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/applicationGateways` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authenticationCertificates` | array | `[]` | | Optional. Authentication certificates of the application gateway resource. | +| `autoscaleMaxCapacity` | int | `-1` | | Optional. Upper bound on number of Application Gateway capacity. | +| `autoscaleMinCapacity` | int | `-1` | | Optional. Lower bound on number of Application Gateway capacity. | +| `backendAddressPools` | array | `[]` | | Optional. Backend address pool of the application gateway resource. | +| `backendHttpSettingsCollection` | array | `[]` | | Optional. Backend http settings of the application gateway resource. | +| `capacity` | int | `2` | | Optional. The number of Application instances to be configured. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customErrorConfigurations` | array | `[]` | | Optional. Custom error configurations of the application gateway resource. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableFips` | bool | | | Optional. Whether FIPS is enabled on the application gateway resource. | +| `enableHttp2` | bool | | | Optional. Whether HTTP2 is enabled on the application gateway resource. | +| `enableRequestBuffering` | bool | | | Optional. Enable request buffering. | +| `enableResponseBuffering` | bool | | | Optional. Enable response buffering. | +| `firewallPolicyId` | string | | | Optional. The resource Id of an associated firewall policy. | +| `frontendIPConfigurations` | array | `[]` | | Optional. Frontend IP addresses of the application gateway resource. | +| `frontendPorts` | array | `[]` | | Optional. Frontend ports of the application gateway resource. | +| `gatewayIPConfigurations` | array | `[]` | | Optional. Subnets of the application gateway resource. | +| `httpListeners` | array | `[]` | | Optional. Http listeners of the application gateway resource. | +| `loadDistributionPolicies` | array | `[]` | | Optional. Load distribution policies of the application gateway resource. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ApplicationGatewayAccessLog, ApplicationGatewayPerformanceLog, ApplicationGatewayFirewallLog]` | `[ApplicationGatewayAccessLog, ApplicationGatewayPerformanceLog, ApplicationGatewayFirewallLog]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the Application Gateway. | +| `privateLinkConfigurations` | array | `[]` | | Optional. PrivateLink configurations on application gateway. | +| `probes` | array | `[]` | | Optional. Probes of the application gateway resource. | +| `redirectConfigurations` | array | `[]` | | Optional. Redirect configurations of the application gateway resource. | +| `requestRoutingRules` | array | `[]` | | Optional. Request routing rules of the application gateway resource. | +| `rewriteRuleSets` | array | `[]` | | Optional. Rewrite rules for the application gateway resource. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `WAF_Medium` | `[Standard_Small, Standard_Medium, Standard_Large, WAF_Medium, WAF_Large, Standard_v2, WAF_v2]` | Optional. The name of the SKU for the Application Gateway. | +| `sslCertificates` | array | `[]` | | Optional. SSL certificates of the application gateway resource. | +| `sslPolicyCipherSuites` | array | `[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]` | `[TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384]` | Optional. Ssl cipher suites to be enabled in the specified order to application gateway. | +| `sslPolicyMinProtocolVersion` | string | `TLSv1_2` | `[TLSv1_0, TLSv1_1, TLSv1_2]` | Optional. Ssl protocol enums. | +| `sslPolicyName` | string | | `[AppGwSslPolicy20150501, AppGwSslPolicy20170401, AppGwSslPolicy20170401S, ]` | Optional. Ssl predefined policy name enums. | +| `sslPolicyType` | string | `Custom` | `[Custom, Predefined]` | Optional. Type of Ssl Policy. | +| `sslProfiles` | array | `[]` | | Optional. SSL profiles of the application gateway resource. | +| `tags` | object | `{object}` | | Optional. Resource tags. | +| `trustedClientCertificates` | array | `[]` | | Optional. Trusted client certificates of the application gateway resource. | +| `trustedRootCertificates` | array | `[]` | | Optional. Trusted Root certificates of the application gateway resource. | +| `urlPathMaps` | array | `[]` | | Optional. URL path map of the application gateway resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `webApplicationFirewallConfiguration` | object | `{object}` | | Optional. Application gateway web application firewall configuration. | +| `zones` | array | `[]` | | Optional. A list of availability zones denoting where the resource needs to come from. | + +### Parameter Usage: `authenticationCertificates` + +```json +"authenticationCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string" + } + } + ] +} +``` + +### Parameter Usage: `backendAddressPools` + +```json +"backendAddressPools": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddresses": [ + { + "fqdn": "string", + "ipAddress": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `backendHttpSettingsCollection` + +```json +"backendHttpSettingsCollection": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "affinityCookieName": "string", + "authenticationCertificates": [ + { + "id": "string" + } + ], + "connectionDraining": { + "drainTimeoutInSec": "int", + "enabled": "bool" + }, + "cookieBasedAffinity": "string", + "hostName": "string", + "path": "string", + "pickHostNameFromBackendAddress": "bool", + "port": "int", + "probe": { + "id": "string" + }, + "probeEnabled": "bool", + "protocol": "string", + "requestTimeout": "int", + "trustedRootCertificates": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `customErrorConfigurations` + +```json +"customErrorConfigurations": { + "value": [ + { + "customErrorPageUrl": "string", + "statusCode": "string" + } + ] +} +``` + +### Parameter Usage: `frontendIPConfigurations` + +```json +"frontendIPConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "privateIPAddress": "string", + "privateIPAllocationMethod": "string", + "privateLinkConfiguration": { + "id": "string" + }, + "publicIPAddress": { + "id": "string" + }, + "subnet": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `frontendPorts` + +```json +"frontendPorts": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "port": "int" + } + } + ] +} +``` + +### Parameter Usage: `gatewayIPConfigurations` + +```json +"gatewayIPConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "subnet": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `httpListeners` + +```json +"httpListeners": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "customErrorConfigurations": [ + { + "customErrorPageUrl": "string", + "statusCode": "string" + } + ], + "firewallPolicy": { + "id": "string" + }, + "frontendIPConfiguration": { + "id": "string" + }, + "frontendPort": { + "id": "string" + }, + "hostName": "string", + "hostNames": [ "string" ], + "protocol": "string", + "requireServerNameIndication": "bool", + "sslCertificate": { + "id": "string" + }, + "sslProfile": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `loadDistributionPolicies` + +```json +"loadDistributionPolicies": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "loadDistributionAlgorithm": "string", + "loadDistributionTargets": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "weightPerServer": "int" + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `privateLinkConfigurations` + +```json +"privateLinkConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "ipConfigurations": [ + { + "id": "string", + "name": "string", + "properties": { + "primary": "bool", + "privateIPAddress": "string", + "privateIPAllocationMethod": "string", + "subnet": { + "id": "string" + } + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `probes` + +```json +"probes": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "host": "string", + "interval": "int", + "match": { + "body": "string", + "statusCodes": [ "string" ] + }, + "minServers": "int", + "path": "string", + "pickHostNameFromBackendHttpSettings": "bool", + "port": "int", + "protocol": "string", + "timeout": "int", + "unhealthyThreshold": "int" + } + } + ] +} +``` + +### Parameter Usage: `redirectConfigurations` + +```json +"redirectConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "includePath": "bool", + "includeQueryString": "bool", + "pathRules": [ + { + "id": "string" + } + ], + "redirectType": "string", + "requestRoutingRules": [ + { + "id": "string" + } + ], + "targetListener": { + "id": "string" + }, + "targetUrl": "string", + "urlPathMaps": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `requestRoutingRules` + +```json +"requestRoutingRules": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "backendHttpSettings": { + "id": "string" + }, + "httpListener": { + "id": "string" + }, + "loadDistributionPolicy": { + "id": "string" + }, + "priority": "int", + "redirectConfiguration": { + "id": "string" + }, + "rewriteRuleSet": { + "id": "string" + }, + "ruleType": "string", + "urlPathMap": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `rewriteRuleSets` + +```json +"rewriteRuleSets": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "rewriteRules": [ + { + "actionSet": { + "requestHeaderConfigurations": [ + { + "headerName": "string", + "headerValue": "string" + } + ], + "responseHeaderConfigurations": [ + { + "headerName": "string", + "headerValue": "string" + } + ], + "urlConfiguration": { + "modifiedPath": "string", + "modifiedQueryString": "string", + "reroute": "bool" + } + }, + "conditions": [ + { + "ignoreCase": "bool", + "negate": "bool", + "pattern": "string", + "variable": "string" + } + ], + "name": "string", + "ruleSequence": "int" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `sslCertificates` + +```json +"sslCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string", + "keyVaultSecretId": "string", + "password": "string" + } + } + ] +} +``` + +### Parameter Usage: `sslProfiles` + +```json +"sslProfiles": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "clientAuthConfiguration": { + "verifyClientCertIssuerDN": "bool" + }, + "sslPolicy": { + "cipherSuites": [ "string" ], + "disabledSslProtocols": [ "string" ], + "minProtocolVersion": "string", + "policyName": "string", + "policyType": "string" + }, + "trustedClientCertificates": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `trustedClientCertificates` + +```json +"trustedClientCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string" + } + } + ] +} +``` + +### Parameter Usage: `trustedRootCertificates` + +```json +"trustedRootCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string", + "keyVaultSecretId": "string" + } + } + ] +} +``` + +### Parameter Usage: `urlPathMaps` + +```json +"urlPathMaps": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "defaultBackendAddressPool": { + "id": "string" + }, + "defaultBackendHttpSettings": { + "id": "string" + }, + "defaultLoadDistributionPolicy": { + "id": "string" + }, + "defaultRedirectConfiguration": { + "id": "string" + }, + "defaultRewriteRuleSet": { + "id": "string" + }, + "pathRules": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "backendHttpSettings": { + "id": "string" + }, + "firewallPolicy": { + "id": "string" + }, + "loadDistributionPolicy": { + "id": "string" + }, + "paths": [ "string" ], + "redirectConfiguration": { + "id": "string" + }, + "rewriteRuleSet": { + "id": "string" + } + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application gateway | +| `resourceGroupName` | string | The resource group the application gateway was deployed into | +| `resourceId` | string | The resource ID of the application gateway | + +## Template references + +- [Applicationgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/applicationGateways) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/applicationGateways/version.json b/carml/1.0.0/Microsoft.Network/applicationGateways/version.json new file mode 100644 index 000000000..badc0a228 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationGateways/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.5" +} diff --git a/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6f915c8c8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(applicationSecurityGroup.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: applicationSecurityGroup +}] diff --git a/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json new file mode 100644 index 000000000..f740e20b4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-asg-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep new file mode 100644 index 000000000..5e4b2b646 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep @@ -0,0 +1,61 @@ +@description('Required. Name of the Application Security Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource applicationSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${applicationSecurityGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: applicationSecurityGroup +} + +module applicationSecurityGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppSecurityGroup-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: applicationSecurityGroup.id + } +}] + +@description('The resource group the application security group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the application security group') +output resourceId string = applicationSecurityGroup.id + +@description('The name of the application security group') +output name string = applicationSecurityGroup.name diff --git a/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/readme.md b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/readme.md new file mode 100644 index 000000000..88e3fa2c1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/readme.md @@ -0,0 +1,75 @@ +# Application Security Groups `[Microsoft.Network/applicationSecurityGroups]` + +This module deploys an application security group. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/applicationSecurityGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the Application Security Group. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application security group | +| `resourceGroupName` | string | The resource group the application security group was deployed into | +| `resourceId` | string | The resource ID of the application security group | + +## Template references + +- [Applicationsecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/applicationSecurityGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/version.json b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/applicationSecurityGroups/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/carml/1.0.0/Microsoft.Network/azureFirewalls/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/azureFirewalls/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/azureFirewalls/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..545f3f4ac --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(azureFirewall.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: azureFirewall +}] diff --git a/carml/1.0.0/Microsoft.Network/azureFirewalls/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/azureFirewalls/.parameters/parameters.json new file mode 100644 index 000000000..864f62df5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/azureFirewalls/.parameters/parameters.json @@ -0,0 +1,135 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-azfw-x-001" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + }, + "ipConfigurations": { + "value": [ + { + "name": "ipConfig01", + "publicIPAddressResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-fw", + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-azfw/subnets/AzureFirewallSubnet" + } + ] + }, + "applicationRuleCollections": { + "value": [ + { + "name": "allow-app-rules", + "properties": { + "priority": 100, + "action": { + "type": "allow" + }, + "rules": [ + { + "name": "allow-ase-tags", + "sourceAddresses": [ + "*" + ], + "protocols": [ + { + "protocolType": "HTTP", + "port": "80" + }, + { + "protocolType": "HTTPS", + "port": "443" + } + ], + "fqdnTags": [ + "AppServiceEnvironment", + "WindowsUpdate" + ] + }, + { + "name": "allow-ase-management", + "sourceAddresses": [ + "*" + ], + "protocols": [ + { + "protocolType": "HTTP", + "port": "80" + }, + { + "protocolType": "HTTPS", + "port": "443" + } + ], + "targetFqdns": [ + "management.azure.com" + ] + } + ] + } + } + ] + }, + "networkRuleCollections": { + "value": [ + { + "name": "allow-network-rules", + "properties": { + "priority": 100, + "action": { + "type": "allow" + }, + "rules": [ + { + "name": "allow-ntp", + "sourceAddresses": [ + "*" + ], + "destinationAddresses": [ + "*" + ], + "destinationPorts": [ + "123", + "12000" + ], + "protocols": [ + "Any" + ] + } + ] + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/azureFirewalls/deploy.bicep b/carml/1.0.0/Microsoft.Network/azureFirewalls/deploy.bicep new file mode 100644 index 000000000..3388f582c --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/azureFirewalls/deploy.bicep @@ -0,0 +1,212 @@ +@description('Required. Name of the Azure Firewall.') +param name string + +@description('Optional. Name of an Azure Firewall SKU.') +@allowed([ + 'AZFW_VNet' + 'AZFW_Hub' +]) +param azureSkuName string = 'AZFW_VNet' + +@description('Optional. Tier of an Azure Firewall.') +@allowed([ + 'Standard' + 'Premium' +]) +param azureSkuTier string = 'Standard' + +@description('Optional. Collection of application rule collections used by Azure Firewall.') +param applicationRuleCollections array = [] + +@description('Optional. Collection of network rule collections used by Azure Firewall.') +param networkRuleCollections array = [] + +@description('Optional. Collection of NAT rule collections used by Azure Firewall.') +param natRuleCollections array = [] + +@description('Required. List of IP Configurations.') +param ipConfigurations array + +@description('Optional. Resource ID of the Firewall Policy that should be attached.') +param firewallPolicyId string = '' + +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +@description('Optional. The operation mode for Threat Intel.') +param threatIntelMode string = 'Deny' + +@description('Optional. Zone numbers e.g. 1,2,3.') +param zones array = [ + '1' + '2' + '3' +] + +@description('Optional. Diagnostic Storage Account resource identifier') +param diagnosticStorageAccountId string = '' + +@description('Optional. Log Analytics workspace resource identifier') +param diagnosticWorkspaceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the Azure Firewall resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of firewall logs that will be streamed.') +@allowed([ + 'AzureFirewallApplicationRule' + 'AzureFirewallNetworkRule' + 'AzureFirewallDnsProxy' +]) +param logsToEnable array = [ + 'AzureFirewallApplicationRule' + 'AzureFirewallNetworkRule' + 'AzureFirewallDnsProxy' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var ipConfigurations_var = [for ipConfiguration in ipConfigurations: { + name: ipConfiguration.name + properties: { + publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? { + id: ipConfiguration.publicIPAddressResourceId + } : null + subnet: contains(ipConfiguration, 'subnetResourceId') ? { + id: ipConfiguration.subnetResourceId + } : null + } +}] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2021-05-01' = { + name: name + location: location + zones: length(zones) == 0 ? null : zones + tags: tags + properties: { + threatIntelMode: threatIntelMode + firewallPolicy: empty(firewallPolicyId) ? null : { + id: firewallPolicyId + } + ipConfigurations: ipConfigurations_var + sku: { + name: azureSkuName + tier: azureSkuTier + } + applicationRuleCollections: applicationRuleCollections + natRuleCollections: natRuleCollections + networkRuleCollections: networkRuleCollections + } +} + +resource azureFirewall_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureFirewall.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureFirewall +} + +resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${azureFirewall.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: azureFirewall +} + +module azureFirewall_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AzFW-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureFirewall.id + } +}] + +@description('The resource ID of the Azure firewall') +output resourceId string = azureFirewall.id + +@description('The name of the Azure firewall') +output name string = azureFirewall.name + +@description('The resource group the Azure firewall was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The private IP of the Azure firewall') +output privateIp string = azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + +@description('List of Application Rule Collections') +output applicationRuleCollections array = applicationRuleCollections + +@description('List of Network Rule Collections') +output networkRuleCollections array = networkRuleCollections + +@description('Collection of NAT rule collections used by Azure Firewall') +output natRuleCollections array = natRuleCollections diff --git a/carml/1.0.0/Microsoft.Network/azureFirewalls/readme.md b/carml/1.0.0/Microsoft.Network/azureFirewalls/readme.md new file mode 100644 index 000000000..3abb12c49 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/azureFirewalls/readme.md @@ -0,0 +1,102 @@ +# Azure Firewalls `[Microsoft.Network/azureFirewalls]` + +This module deploys a firewall. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/azureFirewalls` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `applicationRuleCollections` | array | `[]` | | Optional. Collection of application rule collections used by Azure Firewall. | +| `azureSkuName` | string | `AZFW_VNet` | `[AZFW_VNet, AZFW_Hub]` | Optional. Name of an Azure Firewall SKU. | +| `azureSkuTier` | string | `Standard` | `[Standard, Premium]` | Optional. Tier of an Azure Firewall. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Diagnostic Storage Account resource identifier | +| `diagnosticWorkspaceId` | string | | | Optional. Log Analytics workspace resource identifier | +| `firewallPolicyId` | string | | | Optional. Resource ID of the Firewall Policy that should be attached. | +| `ipConfigurations` | array | | | Required. List of IP Configurations. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[AzureFirewallApplicationRule, AzureFirewallNetworkRule, AzureFirewallDnsProxy]` | `[AzureFirewallApplicationRule, AzureFirewallNetworkRule, AzureFirewallDnsProxy]` | Optional. The name of firewall logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the Azure Firewall. | +| `natRuleCollections` | array | `[]` | | Optional. Collection of NAT rule collections used by Azure Firewall. | +| `networkRuleCollections` | array | `[]` | | Optional. Collection of network rule collections used by Azure Firewall. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the Azure Firewall resource. | +| `threatIntelMode` | string | `Deny` | `[Alert, Deny, Off]` | Optional. The operation mode for Threat Intel. | +| `zones` | array | `[1, 2, 3]` | | Optional. Zone numbers e.g. 1,2,3. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationRuleCollections` | array | List of Application Rule Collections | +| `name` | string | The name of the Azure firewall | +| `natRuleCollections` | array | Collection of NAT rule collections used by Azure Firewall | +| `networkRuleCollections` | array | List of Network Rule Collections | +| `privateIp` | string | The private IP of the Azure firewall | +| `resourceGroupName` | string | The resource group the Azure firewall was deployed into | +| `resourceId` | string | The resource ID of the Azure firewall | + +## Considerations + +The `applicationRuleCollections` parameter accepts a JSON Array of AzureFirewallApplicationRule objects. +The `networkRuleCollections` parameter accepts a JSON Array of AzureFirewallNetworkRuleCollection objects. + +## Template references + +- [Azurefirewalls](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/azureFirewalls) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/azureFirewalls/version.json b/carml/1.0.0/Microsoft.Network/azureFirewalls/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/azureFirewalls/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/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep new file mode 100644 index 000000000..c0dfd0194 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep @@ -0,0 +1,148 @@ +@description('Required. The name of the Public IP Address') +param name string + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. The public IP address allocation method. - Static or Dynamic.') +param publicIPAllocationMethod string = 'Dynamic' + +@description('Optional. Public IP Address sku Name') +param skuName string = 'Basic' + +@description('Optional. Public IP Address pricing tier') +param skuTier string = 'Regional' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource identifier of log analytics.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param logsToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIPPrefix = { + id: publicIPPrefixResourceId +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + properties: { + publicIPAddressVersion: 'IPv4' + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + idleTimeoutInMinutes: 4 + ipTags: [] + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${publicIpAddress.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac 'nested_publicIPAddress_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The resource group the public IP address was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address') +output resourceId string = publicIpAddress.id diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep new file mode 100644 index 000000000..a900d31e2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep @@ -0,0 +1,40 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: publicIpAddress +}] diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..9d53357a2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource azureBastion 'Microsoft.Network/bastionHosts@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(azureBastion.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: azureBastion +}] diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/bastionHosts/.parameters/min.parameters.json new file mode 100644 index 000000000..6ef38853f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/.parameters/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": "<>-az-bas-min-001" + }, + "vNetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-002" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/bastionHosts/.parameters/parameters.json new file mode 100644 index 000000000..dba5d3d6f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-bas-x-001" + }, + "vNetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "publicIPAddressId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-bas" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/deploy.bicep b/carml/1.0.0/Microsoft.Network/bastionHosts/deploy.bicep new file mode 100644 index 000000000..3c1547cc3 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/deploy.bicep @@ -0,0 +1,169 @@ +@description('Required. Name of the Azure Bastion resource') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Shared services Virtual Network resource identifier') +param vNetId string + +@description('Optional. Specifies the resource ID of the existing public IP to be leveraged by Azure Bastion.') +param publicIPAddressId string = '' + +@description('Optional. Specifies the properties of the public IP to create and be used by Azure Bastion. If it\'s not provided and publicIPAddressId is empty, a \'-pip\' suffix will be appended to the Bastion\'s name.') +param publicIPAddressObject object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Optional. The name of bastion logs that will be streamed.') +@allowed([ + 'BastionAuditLogs' +]) +param logsToEnable array = [ + 'BastionAuditLogs' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource publicIPAddressExisting 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = if (!empty(publicIPAddressId)) { + name: last(split(publicIPAddressId, '/')) + scope: resourceGroup(split(publicIPAddressId, '/')[2], split(publicIPAddressId, '/')[4]) +} + +module publicIPAddress '.bicep/nested_publicIPAddress.bicep' = if (empty(publicIPAddressId)) { + name: '${uniqueString(deployment().name, location)}-Bastion-PIP' + params: { + name: contains(publicIPAddressObject, 'name') ? (!(empty(publicIPAddressObject.name)) ? publicIPAddressObject.name : '${name}-pip') : '${name}-pip' + publicIPPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) ? publicIPAddressObject.publicIPPrefixResourceId : '') : '' + publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) ? publicIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' + skuName: contains(publicIPAddressObject, 'skuName') ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') : 'Standard' + skuTier: contains(publicIPAddressObject, 'skuTier') ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') : 'Regional' + roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) : [] + metricsToEnable: contains(publicIPAddressObject, 'metricsToEnable') ? (!(empty(publicIPAddressObject.metricsToEnable)) ? publicIPAddressObject.metricsToEnable : [ + 'AllMetrics' + ]) : [ + 'AllMetrics' + ] + logsToEnable: contains(publicIPAddressObject, 'logsToEnable') ? (!(empty(publicIPAddressObject.logsToEnable)) ? publicIPAddressObject.logsToEnable : [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' + ]) : [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' + ] + location: location + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + lock: lock + tags: tags + } +} + +resource azureBastion 'Microsoft.Network/bastionHosts@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipConfigurations: [ + { + name: 'IpConf' + properties: { + subnet: { + id: '${vNetId}/subnets/AzureBastionSubnet' + } + publicIPAddress: { + id: !(empty(publicIPAddressId)) ? publicIPAddressId : publicIPAddress.outputs.resourceId + } + } + } + ] + } +} + +resource azureBastion_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureBastion.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureBastion +} + +resource azureBastion_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${azureBastion.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: azureBastion +} + +module azureBastion_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Bastion-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureBastion.id + } +}] + +@description('The resource group the Azure Bastion was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name the Azure Bastion') +output name string = azureBastion.name + +@description('The resource ID the Azure Bastion') +output resourceId string = azureBastion.id diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/readme.md b/carml/1.0.0/Microsoft.Network/bastionHosts/readme.md new file mode 100644 index 000000000..80f42cf38 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/readme.md @@ -0,0 +1,88 @@ +# Bastion Hosts `[Microsoft.Network/bastionHosts]` + +This module deploys a bastion host. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/bastionHosts` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[BastionAuditLogs]` | `[BastionAuditLogs]` | Optional. Optional. The name of bastion logs that will be streamed. | +| `name` | string | | | Required. Name of the Azure Bastion resource | +| `publicIPAddressId` | string | | | Optional. Specifies the resource ID of the existing public IP to be leveraged by Azure Bastion. | +| `publicIPAddressObject` | object | `{object}` | | Optional. Specifies the properties of the public IP to create and be used by Azure Bastion. If it's not provided and publicIPAddressId is empty, a '-pip' suffix will be appended to the Bastion's name. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `vNetId` | string | | | Required. Shared services Virtual Network resource identifier | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name the Azure Bastion | +| `resourceGroupName` | string | The resource group the Azure Bastion was deployed into | +| `resourceId` | string | The resource ID the Azure Bastion | + +## Template references + +- [Bastionhosts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/bastionHosts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/bastionHosts/version.json b/carml/1.0.0/Microsoft.Network/bastionHosts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/bastionHosts/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/carml/1.0.0/Microsoft.Network/connections/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/connections/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/connections/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/connections/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/connections/.parameters/parameters.json new file mode 100644 index 000000000..147e3d69b --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/connections/.parameters/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": "<>-az-vnetgwc-x-001" + }, + "localVirtualNetworkGatewayName": { + "value": "<>-az-vnet-vpn-gw-p-001" + }, + "vpnSharedKey": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "vpnSharedKey" + } + }, + "virtualNetworkGatewayConnectionType": { + "value": "VNet2VNet" + }, + "remoteEntityName": { + "value": "<>-az-vnet-vpn-gw-p-002" + }, + "remoteEntityResourceGroup": { + "value": "" + }, + "remoteEntitySubscriptionId": { + "value": "" + }, + "enableBgp": { + "value": false + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/connections/deploy.bicep b/carml/1.0.0/Microsoft.Network/connections/deploy.bicep new file mode 100644 index 000000000..59ebbd3f9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/connections/deploy.bicep @@ -0,0 +1,132 @@ +@description('Required. Remote connection name') +param name string + +@description('Optional. Specifies a VPN shared key. The same value has to be specified on both Virtual Network Gateways') +param vpnSharedKey string = '' + +@description('Required. Specifies the remote Virtual Network Gateway/ExpressRoute') +param remoteEntityName string + +@description('Required. Specifies the local Virtual Network Gateway name') +param localVirtualNetworkGatewayName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Gateway connection type.') +@allowed([ + 'Ipsec' + 'VNet2VNet' + 'ExpressRoute' + 'VPNClient' +]) +param virtualNetworkGatewayConnectionType string = 'Ipsec' + +@description('Optional. Remote Virtual Network Gateway/ExpressRoute resource group name') +param remoteEntityResourceGroup string = '' + +@description('Optional. Remote Virtual Network Gateway/ExpressRoute Subscription ID') +param remoteEntitySubscriptionId string = '' + +@description('Optional. Value to specify if BGP is enabled or not') +param enableBgp bool = false + +@description('Optional. Enable policy-based traffic selectors') +param usePolicyBasedTrafficSelectors bool = false + +@description('Optional. The IPSec Policies to be considered by this connection') +param customIPSecPolicy object = { + saLifeTimeSeconds: 0 + saDataSizeKilobytes: 0 + ipsecEncryption: '' + ipsecIntegrity: '' + ikeEncryption: '' + ikeIntegrity: '' + dhGroup: '' + pfsGroup: '' +} + +@description('Optional. The weight added to routes learned from this BGP speaker.') +param routingWeight string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var localVirtualNetworkGatewayId = az.resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworkGateways', localVirtualNetworkGatewayName) +var remoteEntitySubscriptionId_var = (empty(remoteEntitySubscriptionId) ? subscription().subscriptionId : remoteEntitySubscriptionId) +var remoteEntityResourceGroup_var = (empty(remoteEntityResourceGroup) ? resourceGroup().name : remoteEntityResourceGroup) +var virtualNetworkGateway2Id = { + id: az.resourceId(remoteEntitySubscriptionId_var, remoteEntityResourceGroup_var, 'Microsoft.Network/virtualNetworkGateways', remoteEntityName) +} +var localNetworkGateway2Id = { + id: az.resourceId(remoteEntitySubscriptionId_var, remoteEntityResourceGroup_var, 'Microsoft.Network/localNetworkGateways', remoteEntityName) +} +var peer = { + id: az.resourceId(remoteEntitySubscriptionId_var, remoteEntityResourceGroup_var, 'Microsoft.Network/expressRouteCircuits', remoteEntityName) +} +var customIPSecPolicy_var = [ + { + saLifeTimeSeconds: customIPSecPolicy.saLifeTimeSeconds + saDataSizeKilobytes: customIPSecPolicy.saDataSizeKilobytes + ipsecEncryption: customIPSecPolicy.ipsecEncryption + ipsecIntegrity: customIPSecPolicy.ipsecIntegrity + ikeEncryption: customIPSecPolicy.ikeEncryption + ikeIntegrity: customIPSecPolicy.ikeIntegrity + dhGroup: customIPSecPolicy.dhGroup + pfsGroup: customIPSecPolicy.pfsGroup + } +] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource connection 'Microsoft.Network/connections@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + virtualNetworkGateway1: { + id: localVirtualNetworkGatewayId + } + virtualNetworkGateway2: virtualNetworkGatewayConnectionType == 'VNet2VNet' ? virtualNetworkGateway2Id : null + localNetworkGateway2: virtualNetworkGatewayConnectionType == 'Ipsec' ? localNetworkGateway2Id : null + peer: virtualNetworkGatewayConnectionType == 'ExpressRoute' ? peer : null + enableBgp: enableBgp + connectionType: virtualNetworkGatewayConnectionType + routingWeight: routingWeight + sharedKey: virtualNetworkGatewayConnectionType == 'ExpressRoute' ? null : vpnSharedKey + usePolicyBasedTrafficSelectors: usePolicyBasedTrafficSelectors + ipsecPolicies: empty(customIPSecPolicy.ipsecEncryption) ? customIPSecPolicy.ipsecEncryption : customIPSecPolicy_var + } +} + +resource connection_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${connection.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: connection +} + +@description('The resource group the remote connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the remote connection') +output name string = connection.name + +@description('The resource ID of the remote connection') +output resourceId string = connection.id diff --git a/carml/1.0.0/Microsoft.Network/connections/readme.md b/carml/1.0.0/Microsoft.Network/connections/readme.md new file mode 100644 index 000000000..7ee278fe5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/connections/readme.md @@ -0,0 +1,96 @@ +# Virtual Network Gateway Connections `[Microsoft.Network/connections]` + +This template deploys a virtual network gateway connection. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/connections` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customIPSecPolicy` | object | `{object}` | | Optional. The IPSec Policies to be considered by this connection | +| `enableBgp` | bool | | | Optional. Value to specify if BGP is enabled or not | +| `localVirtualNetworkGatewayName` | string | | | Required. Specifies the local Virtual Network Gateway name | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Remote connection name | +| `remoteEntityName` | string | | | Required. Specifies the remote Virtual Network Gateway/ExpressRoute | +| `remoteEntityResourceGroup` | string | | | Optional. Remote Virtual Network Gateway/ExpressRoute resource group name | +| `remoteEntitySubscriptionId` | string | | | Optional. Remote Virtual Network Gateway/ExpressRoute Subscription ID | +| `routingWeight` | string | | | Optional. The weight added to routes learned from this BGP speaker. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `usePolicyBasedTrafficSelectors` | bool | | | Optional. Enable policy-based traffic selectors | +| `virtualNetworkGatewayConnectionType` | string | `Ipsec` | `[Ipsec, VNet2VNet, ExpressRoute, VPNClient]` | Optional. Gateway connection type. | +| `vpnSharedKey` | string | | | Optional. Specifies a VPN shared key. The same value has to be specified on both Virtual Network Gateways | + +### Parameter Usage: `customIPSecPolicy` + +If ipsecEncryption parameter is empty, customIPSecPolicy will not be deployed. The parameter file should look like below. + +```json +"customIPSecPolicy": { + "value": { + "saLifeTimeSeconds": 0, + "saDataSizeKilobytes": 0, + "ipsecEncryption": "", + "ipsecIntegrity": "", + "ikeEncryption": "", + "ikeIntegrity": "", + "dhGroup": "", + "pfsGroup": "" + } +}, +``` + +Format of the full customIPSecPolicy parameter in parameter file. + +```json +"customIPSecPolicy": { + "value": { + "saLifeTimeSeconds": 28800, + "saDataSizeKilobytes": 102400000, + "ipsecEncryption": "AES256", + "ipsecIntegrity": "SHA256", + "ikeEncryption": "AES256", + "ikeIntegrity": "SHA256", + "dhGroup": "DHGroup14", + "pfsGroup": "None" + } +}, +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the remote connection | +| `resourceGroupName` | string | The resource group the remote connection was deployed into | +| `resourceId` | string | The resource ID of the remote connection | + +## Template references + +- [Connections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/connections) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.0/Microsoft.Network/connections/version.json b/carml/1.0.0/Microsoft.Network/connections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/connections/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/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e1468d6eb --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(ddosProtectionPlan.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: ddosProtectionPlan +}] diff --git a/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json new file mode 100644 index 000000000..3d697dee9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ddos-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/deploy.bicep b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/deploy.bicep new file mode 100644 index 000000000..bd1c9d332 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/deploy.bicep @@ -0,0 +1,62 @@ +@description('Required. Name of the DDoS protection plan to assign the VNET to.') +@minLength(1) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource ddosProtectionPlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${ddosProtectionPlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: ddosProtectionPlan +} + +module ddosProtectionPlan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DDoSProtectionPlan-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: ddosProtectionPlan.id + } +}] + +@description('The resource group the DDOS protection plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the DDOS protection plan') +output resourceId string = ddosProtectionPlan.id + +@description('The name of the DDOS protection plan') +output name string = ddosProtectionPlan.name diff --git a/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/readme.md b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/readme.md new file mode 100644 index 000000000..097028aa8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/readme.md @@ -0,0 +1,75 @@ +# DDoS Protection Plans `[Microsoft.Network/ddosProtectionPlans]` + +This template deploys a DDoS protection plan. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/ddosProtectionPlans` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the DDoS protection plan to assign the VNET to. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the DDOS protection plan | +| `resourceGroupName` | string | The resource group the DDOS protection plan was deployed into | +| `resourceId` | string | The resource ID of the DDOS protection plan | + +## Template references + +- [Ddosprotectionplans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/ddosProtectionPlans) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/version.json b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ddosProtectionPlans/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/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..f5e3afb9c --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(expressRouteCircuits.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: expressRouteCircuits +}] diff --git a/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json new file mode 100644 index 000000000..8050f4406 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-erc-x-001" + }, + "serviceProviderName": { + "value": "Equinix" + }, + "peeringLocation": { + "value": "Amsterdam" + }, + "bandwidthInMbps": { + "value": 50 + }, + "skuTier": { + "value": "Standard" + }, + "skuFamily": { + "value": "MeteredData" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/expressRouteCircuits/deploy.bicep b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/deploy.bicep new file mode 100644 index 000000000..725d93d24 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/deploy.bicep @@ -0,0 +1,208 @@ +@description('Required. This is the name of the ExpressRoute circuit') +param name string + +@description('Required. This is the name of the ExpressRoute Service Provider. It must exactly match one of the Service Providers from List ExpressRoute Service Providers API call.') +param serviceProviderName string + +@description('Required. This is the name of the peering location and not the ARM resource location. It must exactly match one of the available peering locations from List ExpressRoute Service Providers API call.') +param peeringLocation string + +@description('Required. This is the bandwidth in Mbps of the circuit being created. It must exactly match one of the available bandwidth offers List ExpressRoute Service Providers API call.') +param bandwidthInMbps int + +@description('Required. Chosen SKU Tier of ExpressRoute circuit. Choose from Local, Premium or Standard SKU tiers.') +@allowed([ + 'Local' + 'Standard' + 'Premium' +]) +param skuTier string = 'Standard' + +@description('Required. Chosen SKU family of ExpressRoute circuit. Choose from MeteredData or UnlimitedData SKU families.') +@allowed([ + 'MeteredData' + 'UnlimitedData' +]) +param skuFamily string = 'MeteredData' + +@description('Optional. Enabled BGP peering type for the Circuit.') +@allowed([ + true + false +]) +param peering bool = false + +@description('Optional. BGP peering type for the Circuit. Choose from AzurePrivatePeering, AzurePublicPeering or MicrosoftPeering.') +@allowed([ + 'AzurePrivatePeering' + 'MicrosoftPeering' +]) +param peeringType string = 'AzurePrivatePeering' + +@description('Optional. The shared key for peering configuration. Router does MD5 hash comparison to validate the packets sent by BGP connection. This parameter is optional and can be removed from peering configuration if not required.') +param sharedKey string = '' + +@description('Optional. The autonomous system number of the customer/connectivity provider.') +param peerASN int = 0 + +@description('Optional. A /30 subnet used to configure IP addresses for interfaces on Link1.') +param primaryPeerAddressPrefix string = '' + +@description('Optional. A /30 subnet used to configure IP addresses for interfaces on Link2.') +param secondaryPeerAddressPrefix string = '' + +@description('Optional. Specifies the identifier that is used to identify the customer.') +param vlanId int = 0 + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'PeeringRouteLog' +]) +param logsToEnable array = [ + 'PeeringRouteLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var peeringConfiguration = [ + { + name: peeringType + properties: { + peeringType: peeringType + sharedKey: sharedKey + peerASN: peerASN + primaryPeerAddressPrefix: primaryPeerAddressPrefix + secondaryPeerAddressPrefix: secondaryPeerAddressPrefix + vlanId: vlanId + } + } +] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: '${skuTier}_${skuFamily}' + tier: skuTier + family: skuTier == 'Local' ? 'UnlimitedData' : skuFamily + } + properties: { + serviceProviderProperties: { + serviceProviderName: serviceProviderName + peeringLocation: peeringLocation + bandwidthInMbps: bandwidthInMbps + } + peerings: peering ? peeringConfiguration : null + } +} + +resource expressRouteCircuits_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${expressRouteCircuits.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: expressRouteCircuits +} + +resource expressRouteCircuits_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${expressRouteCircuits.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: expressRouteCircuits +} + +module expressRouteCircuits_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ExpRouteCircuits-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: expressRouteCircuits.id + } +}] + +@description('The resource ID of express route curcuit') +output resourceId string = expressRouteCircuits.id + +@description('The resource group the express route curcuit was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of express route curcuit') +output name string = expressRouteCircuits.name + +@description('The service key of the express route circuit') +output serviceKey string = reference(expressRouteCircuits.id, '2021-02-01').serviceKey diff --git a/carml/1.0.0/Microsoft.Network/expressRouteCircuits/readme.md b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/readme.md new file mode 100644 index 000000000..3017157c3 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/readme.md @@ -0,0 +1,97 @@ +# ExpressRoute Circuits `[Microsoft.Network/expressRouteCircuits]` + +This template deploys an express route circuit. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/expressRouteCircuits` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `bandwidthInMbps` | int | | | Required. This is the bandwidth in Mbps of the circuit being created. It must exactly match one of the available bandwidth offers List ExpressRoute Service Providers API call. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[PeeringRouteLog]` | `[PeeringRouteLog]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. This is the name of the ExpressRoute circuit | +| `peerASN` | int | | | Optional. The autonomous system number of the customer/connectivity provider. | +| `peering` | bool | | `[True, False]` | Optional. Enabled BGP peering type for the Circuit. | +| `peeringLocation` | string | | | Required. This is the name of the peering location and not the ARM resource location. It must exactly match one of the available peering locations from List ExpressRoute Service Providers API call. | +| `peeringType` | string | `AzurePrivatePeering` | `[AzurePrivatePeering, MicrosoftPeering]` | Optional. BGP peering type for the Circuit. Choose from AzurePrivatePeering, AzurePublicPeering or MicrosoftPeering. | +| `primaryPeerAddressPrefix` | string | | | Optional. A /30 subnet used to configure IP addresses for interfaces on Link1. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `secondaryPeerAddressPrefix` | string | | | Optional. A /30 subnet used to configure IP addresses for interfaces on Link2. | +| `serviceProviderName` | string | | | Required. This is the name of the ExpressRoute Service Provider. It must exactly match one of the Service Providers from List ExpressRoute Service Providers API call. | +| `sharedKey` | string | | | Optional. The shared key for peering configuration. Router does MD5 hash comparison to validate the packets sent by BGP connection. This parameter is optional and can be removed from peering configuration if not required. | +| `skuFamily` | string | `MeteredData` | `[MeteredData, UnlimitedData]` | Required. Chosen SKU family of ExpressRoute circuit. Choose from MeteredData or UnlimitedData SKU families. | +| `skuTier` | string | `Standard` | `[Local, Standard, Premium]` | Required. Chosen SKU Tier of ExpressRoute circuit. Choose from Local, Premium or Standard SKU tiers. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `vlanId` | int | | | Optional. Specifies the identifier that is used to identify the customer. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of express route curcuit | +| `resourceGroupName` | string | The resource group the express route curcuit was deployed into | +| `resourceId` | string | The resource ID of express route curcuit | +| `serviceKey` | string | The service key of the express route circuit | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Expressroutecircuits](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/expressRouteCircuits) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/expressRouteCircuits/version.json b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/expressRouteCircuits/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/carml/1.0.0/Microsoft.Network/firewallPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/firewallPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json new file mode 100644 index 000000000..bb555089e --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fwpol-min-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/firewallPolicies/.parameters/parameters.json new file mode 100644 index 000000000..67e03ad34 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fwpol-x-002" + }, + "ruleCollectionGroups": { + "value": [ + { + "name": "<>-rule-001", + "priority": 5000, + "ruleCollections": [ + { + "name": "collection002", + "priority": 5555, + "action": { + "type": "Allow" + }, + "rules": [ + { + "name": "rule002", + "ipProtocols": [ + "TCP", + "UDP" + ], + "destinationPorts": [ + "80" + ], + "sourceAddresses": [ + "*" + ], + "sourceIpGroups": [], + "ruleType": "NetworkRule", + "destinationIpGroups": [], + "destinationAddresses": [ + "*" + ], + "destinationFqdns": [] + } + ], + "ruleCollectionType": "FirewallPolicyFilterRuleCollection" + } + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Network/firewallPolicies/deploy.bicep new file mode 100644 index 000000000..8edc96524 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/deploy.bicep @@ -0,0 +1,181 @@ +@description('Required. Name of the Firewall Policy.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Firewall policy resource.') +param tags object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Resource ID of the base policy.') +param basePolicyResourceId string = '' + +@description('Optional. Enable DNS Proxy on Firewalls attached to the Firewall Policy.') +param enableProxy bool = false + +@description('Optional. List of Custom DNS Servers.') +param servers array = [] + +@description('Optional. A flag to indicate if the insights are enabled on the policy.') +param insightsIsEnabled bool = false + +@description('Optional. Default Log Analytics Resource ID for Firewall Policy Insights.') +param defaultWorkspaceId string = '' + +@description('Optional. List of workspaces for Firewall Policy Insights.') +param workspaces array = [] + +@description('Optional. Number of days the insights should be enabled on the policy.') +param retentionDays int = 365 + +@description('Optional. List of rules for traffic to bypass.') +param bypassTrafficSettings array = [] + +@description('Optional. List of specific signatures states.') +param signatureOverrides array = [] + +@description('Optional. The configuring of intrusion detection.') +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +param mode string = 'Off' + +@description('Optional. Tier of Firewall Policy.') +@allowed([ + 'Premium' + 'Standard' +]) +param tier string = 'Standard' + +@description('Optional. List of private IP addresses/IP address ranges to not be SNAT.') +param privateRanges array = [] + +@description('Optional. The operation mode for Threat Intel.') +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +param threatIntelMode string = 'Off' + +@description('Optional. List of FQDNs for the ThreatIntel Allowlist.') +param fqdns array = [] + +@description('Optional. List of IP addresses for the ThreatIntel Allowlist.') +param ipAddresses array = [] + +@description('Optional. Secret Id of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault. ') +param keyVaultSecretId string = '' + +@description('Optional. Name of the CA certificate.') +param certificateName string = '' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Rule collection groups.') +param ruleCollectionGroups array = [] + +@description('Optional. Rule groups.') +param ruleGroups array = [] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + basePolicy: !empty(basePolicyResourceId) ? { + id: basePolicyResourceId + } : null + dnsSettings: enableProxy ? { + enableProxy: enableProxy + servers: servers + } : null + insights: insightsIsEnabled ? { + isEnabled: insightsIsEnabled + logAnalyticsResources: { + defaultWorkspaceId: { + id: !empty(defaultWorkspaceId) ? defaultWorkspaceId : null + } + workspaces: !empty(workspaces) ? workspaces : null + } + retentionDays: retentionDays + } : null + intrusionDetection: (mode != 'Off') ? { + configuration: { + bypassTrafficSettings: !empty(bypassTrafficSettings) ? bypassTrafficSettings : null + signatureOverrides: !empty(signatureOverrides) ? signatureOverrides : null + } + mode: mode + } : null + sku: { + tier: tier + } + snat: !empty(privateRanges) ? { + privateRanges: privateRanges + } : null + threatIntelMode: threatIntelMode + threatIntelWhitelist: { + fqdns: fqdns + ipAddresses: ipAddresses + } + transportSecurity: (!empty(keyVaultSecretId) || !empty(certificateName)) ? { + certificateAuthority: { + keyVaultSecretId: !empty(keyVaultSecretId) ? keyVaultSecretId : null + name: !empty(certificateName) ? certificateName : null + } + } : null + } +} + +@batchSize(1) +module firewallPolicy_ruleCollectionGroups 'ruleCollectionGroups/deploy.bicep' = [for (ruleCollectionGroup, index) in ruleCollectionGroups: { + name: '${uniqueString(deployment().name, location)}-firewallPolicy_ruleCollectionGroups-${index}' + params: { + firewallPolicyName: firewallPolicy.name + name: ruleCollectionGroup.name + priority: ruleCollectionGroup.priority + ruleCollections: ruleCollectionGroup.ruleCollections + } +}] + +@batchSize(1) +module firewallPolicy_ruleGroups 'ruleGroups/deploy.bicep' = [for (ruleGroup, index) in ruleGroups: { + name: '${uniqueString(deployment().name, location)}-firewallPolicy_ruleGroups-${index}' + params: { + firewallPolicyName: firewallPolicy.name + name: ruleGroup.name + priority: ruleGroup.priority + rules: ruleGroup.rules + } +}] + +@description('The name of the deployed firewall policy') +output name string = firewallPolicy.name + +@description('The resource ID of the deployed firewall policy') +output resourceId string = firewallPolicy.id + +@description('The resource group of the deployed firewall policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/readme.md b/carml/1.0.0/Microsoft.Network/firewallPolicies/readme.md new file mode 100644 index 000000000..2e30425fc --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/readme.md @@ -0,0 +1,85 @@ +# Network Firewall Policies `[Microsoft.Network/firewallPolicies]` + +This module deploys Network Firewall Policies. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies` | 2021-05-01 | +| `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | 2021-05-01 | +| `Microsoft.Network/firewallPolicies/ruleGroups` | 2020-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `basePolicyResourceId` | string | | | Optional. Resource ID of the base policy. | +| `bypassTrafficSettings` | array | `[]` | | Optional. List of rules for traffic to bypass. | +| `certificateName` | string | | | Optional. Name of the CA certificate. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `defaultWorkspaceId` | string | | | Optional. Default Log Analytics Resource ID for Firewall Policy Insights. | +| `enableProxy` | bool | `False` | | Optional. Enable DNS Proxy on Firewalls attached to the Firewall Policy. | +| `fqdns` | array | `[]` | | Optional. List of FQDNs for the ThreatIntel Allowlist. | +| `insightsIsEnabled` | bool | `False` | | Optional. A flag to indicate if the insights are enabled on the policy. | +| `ipAddresses` | array | `[]` | | Optional. List of IP addresses for the ThreatIntel Allowlist. | +| `keyVaultSecretId` | string | | | Optional. Secret Id of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `mode` | string | `Off` | `[Alert, Deny, Off]` | Optional. The configuring of intrusion detection. | +| `name` | string | | | Required. Name of the Firewall Policy. | +| `privateRanges` | array | `[]` | | Optional. List of private IP addresses/IP address ranges to not be SNAT. | +| `retentionDays` | int | `365` | | Optional. Number of days the insights should be enabled on the policy. | +| `ruleCollectionGroups` | _[ruleCollectionGroups](ruleCollectionGroups/readme.md)_ array | `[]` | | Optional. Rule collection groups. | +| `ruleGroups` | _[ruleGroups](ruleGroups/readme.md)_ array | `[]` | | Optional. Rule groups. | +| `servers` | array | `[]` | | Optional. List of Custom DNS Servers. | +| `signatureOverrides` | array | `[]` | | Optional. List of specific signatures states. | +| `systemAssignedIdentity` | bool | `False` | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the Firewall policy resource. | +| `threatIntelMode` | string | `Off` | `[Alert, Deny, Off]` | Optional. The operation mode for Threat Intel. | +| `tier` | string | `Standard` | `[Premium, Standard]` | Optional. Tier of Firewall Policy. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `workspaces` | array | `[]` | | Optional. List of workspaces for Firewall Policy Insights. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed firewall policy | +| `resourceGroupName` | string | The resource group of the deployed firewall policy | +| `resourceId` | string | The resource ID of the deployed firewall policy | + +## Template references + +- ['firewallPolicies/ruleGroups' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/firewallPolicies) +- [Firewallpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies) +- [Firewallpolicies/Rulecollectiongroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies/ruleCollectionGroups) diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep new file mode 100644 index 000000000..72f1ebdfb --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep @@ -0,0 +1,41 @@ +@description('Required. Name of the Firewall Policy.') +param firewallPolicyName string + +@description('Required. The name of the rule collection group to deploy') +param name string + +@description('Required. Priority of the Firewall Policy Rule Collection Group resource.') +param priority int + +@description('Optional. Group of Firewall Policy rule collections.') +param ruleCollections array = [] + +@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 firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' existing = { + name: firewallPolicyName +} + +resource ruleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2021-05-01' = { + name: name + parent: firewallPolicy + properties: { + priority: priority + ruleCollections: ruleCollections + } +} + +@description('The name of the deployed rule collection group') +output name string = ruleCollectionGroup.name + +@description('The resource ID of the deployed rule collection group') +output resourceId string = ruleCollectionGroup.id + +@description('The resource group of the deployed rule collection group') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md new file mode 100644 index 000000000..ad4cb4daf --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md @@ -0,0 +1,46 @@ +# Network Firewall Policies Rule Collection Groups `[Microsoft.Network/firewallPolicies/ruleCollectionGroups]` + +This module deploys Network Firewall Policies Rule Collection Groups. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `firewallPolicyName` | string | | | Required. Name of the Firewall Policy. | +| `name` | string | | | Required. The name of the rule collection group to deploy | +| `priority` | int | | | Required. Priority of the Firewall Policy Rule Collection Group resource. | +| `ruleCollections` | array | `[]` | | Optional. Group of Firewall Policy rule collections. | + +### Parameter Usage: `ruleCollections` + +For remaining properties, see [FirewallPolicyRuleCollection objects](https://docs.microsoft.com/en-us/azure/templates/microsoft.network/firewallpolicies/rulecollectiongroups?tabs=json#firewallpolicyrulecollection-objects) + +```json +"ruleCollections": [ + { + "name": "string", + "priority": "int", + "ruleCollectionType": "string" + // For remaining properties, see FirewallPolicyRuleCollection objects + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed rule collection group | +| `resourceGroupName` | string | The resource group of the deployed rule collection group | +| `resourceId` | string | The resource ID of the deployed rule collection group | + +## Template references + +- [Firewallpolicies/Rulecollectiongroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies/ruleCollectionGroups) diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/version.json b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/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/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/deploy.bicep b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/deploy.bicep new file mode 100644 index 000000000..afd5fc5e1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/deploy.bicep @@ -0,0 +1,41 @@ +@description('Required. Name of the Firewall Policy.') +param firewallPolicyName string + +@description('Required. The name of the rule group to deploy') +param name string + +@description('Required. Priority of the Firewall Policy Rule Group resource.') +param priority int + +@description('Optional. Group of Firewall rules.') +param rules array = [] + +@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 firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' existing = { + name: firewallPolicyName +} + +resource ruleGroup 'Microsoft.Network/firewallPolicies/ruleGroups@2020-04-01' = { + name: name + parent: firewallPolicy + properties: { + priority: priority + rules: rules + } +} + +@description('The name of the deployed rule group') +output name string = ruleGroup.name + +@description('The resource ID of the deployed rule group') +output resourceId string = ruleGroup.id + +@description('The resource group of the deployed rule group') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/readme.md b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/readme.md new file mode 100644 index 000000000..a4fe36d02 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/readme.md @@ -0,0 +1,46 @@ +# Network Firewall Policies Rule Groups `[Microsoft.Network/firewallPolicies/ruleGroups]` + +This module deploys Network FirewallPolicies Rule Groups. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies/ruleGroups` | 2020-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `firewallPolicyName` | string | | | Required. Name of the Firewall Policy. | +| `name` | string | | | Required. The name of the rule group to deploy | +| `priority` | int | | | Required. Priority of the Firewall Policy Rule Group resource. | +| `rules` | array | `[]` | | Optional. Group of Firewall rules. | + +### Parameter Usage: `rules` + +For remaining properties, see [FirewallPolicyRule objects](https://docs.microsoft.com/en-us/azure/templates/microsoft.network/2020-04-01/firewallpolicies/rulegroups?tabs=json#firewallpolicyrule-objects) + +```json +"rules": [ + { + "name": "string", + "priority": "int", + "ruleType": "string" + // For remaining properties, see FirewallPolicyRule objects + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed rule group | +| `resourceGroupName` | string | The resource group of the deployed rule group | +| `resourceId` | string | The resource ID of the deployed rule group | + +## Template references + +- ['firewallPolicies/ruleGroups' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/firewallPolicies) diff --git a/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/version.json b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/ruleGroups/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/carml/1.0.0/Microsoft.Network/firewallPolicies/version.json b/carml/1.0.0/Microsoft.Network/firewallPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/firewallPolicies/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/carml/1.0.0/Microsoft.Network/ipGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/ipGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ipGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..f48c2bb18 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource ipGroup 'Microsoft.Network/ipGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(ipGroup.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: ipGroup +}] diff --git a/carml/1.0.0/Microsoft.Network/ipGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/ipGroups/.parameters/parameters.json new file mode 100644 index 000000000..88c2f5a13 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ipGroups/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "iacsGroup-servers" + }, + "ipAddresses": { + "value": [ + "10.0.0.1", + "10.0.0.2" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/ipGroups/deploy.bicep b/carml/1.0.0/Microsoft.Network/ipGroups/deploy.bicep new file mode 100644 index 000000000..393820036 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ipGroups/deploy.bicep @@ -0,0 +1,67 @@ +@description('Required. The name of the ipGroups.') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. IpAddresses/IpAddressPrefixes in the IpGroups resource.') +param ipAddresses array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@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 ipGroup 'Microsoft.Network/ipGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipAddresses: ipAddresses + } +} + +resource ipGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${ipGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: ipGroup +} + +module ipGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-IPGroup-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: ipGroup.id + } +}] + +@description('The resource ID of the IP group') +output resourceId string = ipGroup.id + +@description('The resource group of the IP group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the IP group') +output name string = ipGroup.name diff --git a/carml/1.0.0/Microsoft.Network/ipGroups/readme.md b/carml/1.0.0/Microsoft.Network/ipGroups/readme.md new file mode 100644 index 000000000..1a6d257e4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ipGroups/readme.md @@ -0,0 +1,76 @@ +# IP Groups `[Microsoft.Network/ipGroups]` + +This module deploys an IP group. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/ipGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `ipAddresses` | array | `[]` | | Optional. IpAddresses/IpAddressPrefixes in the IpGroups resource. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the ipGroups. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Resource tags. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the IP group | +| `resourceGroupName` | string | The resource group of the IP group was deployed into | +| `resourceId` | string | The resource ID of the IP group | + +## Template references + +- [Ipgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/ipGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/ipGroups/version.json b/carml/1.0.0/Microsoft.Network/ipGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/ipGroups/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/carml/1.0.0/Microsoft.Network/loadBalancers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..7888113ca --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep @@ -0,0 +1,38 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(loadBalancer.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: loadBalancer +}] diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/loadBalancers/.parameters/min.parameters.json new file mode 100644 index 000000000..dac87cc92 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/.parameters/min.parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-min-001" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "publicIPConfig1", + "publicIPAddressId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-min-lb", + "subnetId": "", + "privateIPAddress": "" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/loadBalancers/.parameters/parameters.json new file mode 100644 index 000000000..1dd8655e7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/.parameters/parameters.json @@ -0,0 +1,128 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-x-001" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "publicIPConfig1", + "publicIPAddressId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-lb", + "subnetId": "", + "privateIPAddress": "" + } + ] + }, + "backendAddressPools": { + "value": [ + { + "name": "backendAddressPool1" + }, + { + "name": "backendAddressPool2" + } + ] + }, + "loadBalancingRules": { + "value": [ + { + "name": "publicIPLBRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 80, + "backendPort": 80, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "protocol": "Tcp", + "enableTcpReset": false, + "loadDistribution": "Default", + "disableOutboundSnat": true, + "probeName": "probe1", + "backendAddressPoolName": "backendAddressPool1" + }, + { + "name": "publicIPLBRule2", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 8080, + "backendPort": 8080, + "loadDistribution": "Default", + "probeName": "probe2", + "backendAddressPoolName": "backendAddressPool2" + } + ] + }, + "inboundNatRules": { + "value": [ + { + "name": "inboundNatRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 443, + "backendPort": 443, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 4, + "protocol": "Tcp", + "enableTcpReset": false + }, + { + "name": "inboundNatRule2", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 3389, + "backendPort": 3389 + } + ] + }, + "outboundRules": { + "value": [ + { + "name": "outboundRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "backendAddressPoolName": "backendAddressPool1", + "allocatedOutboundPorts": 63984 + } + ] + }, + "probes": { + "value": [ + { + "name": "probe1", + "protocol": "Tcp", + "port": 80, + "intervalInSeconds": 10, + "numberOfProbes": 5 + }, + { + "name": "probe2", + "protocol": "Https", + "port": 443, + "requestPath": "/" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep new file mode 100644 index 000000000..85b118de6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep @@ -0,0 +1,41 @@ +@description('Required. The name of the parent load balancer') +param loadBalancerName string + +@description('Required. The name of the backend address pool') +param name string + +@description('Optional. An array of backend addresses.') +param loadBalancerBackendAddresses array = [] + +@description('Optional. An array of gateway load balancer tunnel interfaces.') +param tunnelInterfaces array = [] + +@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 loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: loadBalancerName +} + +resource backendAddressPool 'Microsoft.Network/loadBalancers/backendAddressPools@2021-05-01' = { + name: name + properties: { + loadBalancerBackendAddresses: loadBalancerBackendAddresses + tunnelInterfaces: tunnelInterfaces + } + parent: loadBalancer +} + +@description('The name of the backend address pool') +output name string = backendAddressPool.name + +@description('The resource ID of the backend address pool') +output resourceId string = backendAddressPool.id + +@description('The resource group the backend address pool was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/readme.md b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/readme.md new file mode 100644 index 000000000..b7930145a --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/readme.md @@ -0,0 +1,31 @@ +# Load Balancers Backend Address Pools `[Microsoft.Network/loadBalancers/backendAddressPools]` + +This module deploys load balancer backend address pools. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/loadBalancers/backendAddressPools` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `loadBalancerBackendAddresses` | array | `[]` | | Optional. An array of backend addresses. | +| `loadBalancerName` | string | | | Required. The name of the parent load balancer | +| `name` | string | | | Required. The name of the backend address pool | +| `tunnelInterfaces` | array | `[]` | | Optional. An array of gateway load balancer tunnel interfaces. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backend address pool | +| `resourceGroupName` | string | The resource group the backend address pool was deployed into | +| `resourceId` | string | The resource ID of the backend address pool | + +## Template references + +- [Loadbalancers/Backendaddresspools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/backendAddressPools) diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/version.json b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/backendAddressPools/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/carml/1.0.0/Microsoft.Network/loadBalancers/deploy.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/deploy.bicep new file mode 100644 index 000000000..fce86c457 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/deploy.bicep @@ -0,0 +1,247 @@ +@description('Required. The Proximity Placement Groups Name') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Name of a load balancer SKU.') +@allowed([ + 'Basic' + 'Standard' +]) +param loadBalancerSku string = 'Standard' + +@description('Required. Array of objects containing all frontend IP configurations') +@minLength(1) +param frontendIPConfigurations array + +@description('Optional. Collection of backend address pools used by a load balancer.') +param backendAddressPools array = [] + +@description('Optional. Array of objects containing all load balancing rules') +param loadBalancingRules array = [] + +@description('Optional. Array of objects containing all probes, these are references in the load balancing rules') +param probes array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Collection of inbound NAT Rules used by a load balancer. Defining inbound NAT rules on your load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. They have to reference individual inbound NAT rules.') +param inboundNatRules array = [] + +@description('Optional. The outbound rules.') +param outboundRules array = [] + +var frontendsSubnets = [for item in frontendIPConfigurations: { + id: item.subnetId +}] +var frontendsPublicIPAddresses = [for item in frontendIPConfigurations: { + id: item.publicIPAddressId +}] +var frontendsObj = { + subnets: frontendsSubnets + publicIPAddresses: frontendsPublicIPAddresses +} + +var frontendIPConfigurations_var = [for (frontendIPConfiguration, index) in frontendIPConfigurations: { + name: frontendIPConfiguration.name + properties: { + subnet: !empty(frontendIPConfiguration.subnetId) ? frontendsObj.subnets[index] : null + publicIPAddress: !empty(frontendIPConfiguration.publicIPAddressId) ? frontendsObj.publicIPAddresses[index] : null + privateIPAddress: !empty(frontendIPConfiguration.privateIPAddress) ? frontendIPConfiguration.privateIPAddress : null + privateIPAllocationMethod: !empty(frontendIPConfiguration.subnetId) ? (empty(frontendIPConfiguration.privateIPAddress) ? 'Dynamic' : 'Static') : null + } +}] + +var loadBalancingRules_var = [for loadBalancingRule in loadBalancingRules: { + name: loadBalancingRule.name + properties: { + backendAddressPool: { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, loadBalancingRule.backendAddressPoolName) + } + backendPort: loadBalancingRule.backendPort + disableOutboundSnat: contains(loadBalancingRule, 'disableOutboundSnat') ? loadBalancingRule.disableOutboundSnat : true + enableFloatingIP: contains(loadBalancingRule, 'enableFloatingIP') ? loadBalancingRule.enableFloatingIP : false + enableTcpReset: contains(loadBalancingRule, 'enableTcpReset') ? loadBalancingRule.enableTcpReset : false + frontendIPConfiguration: { + id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, loadBalancingRule.frontendIPConfigurationName) + } + frontendPort: loadBalancingRule.frontendPort + idleTimeoutInMinutes: contains(loadBalancingRule, 'idleTimeoutInMinutes') ? loadBalancingRule.idleTimeoutInMinutes : 4 + loadDistribution: contains(loadBalancingRule, 'loadDistribution') ? loadBalancingRule.loadDistribution : 'Default' + probe: { + id: '${az.resourceId('Microsoft.Network/loadBalancers', name)}/probes/${loadBalancingRule.probeName}' + } + protocol: contains(loadBalancingRule, 'protocol') ? loadBalancingRule.protocol : 'Tcp' + } +}] + +var outboundRules_var = [for outboundRule in outboundRules: { + name: outboundRule.name + properties: { + frontendIPConfigurations: [ + { + id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, outboundRule.frontendIPConfigurationName) + } + ] + backendAddressPool: { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, outboundRule.backendAddressPoolName) + } + protocol: contains(outboundRule, 'protocol') ? outboundRule.protocol : 'All' + allocatedOutboundPorts: contains(outboundRule, 'allocatedOutboundPorts') ? outboundRule.allocatedOutboundPorts : 63984 + enableTcpReset: contains(outboundRule, 'enableTcpReset') ? outboundRule.enableTcpReset : true + idleTimeoutInMinutes: contains(outboundRule, 'idleTimeoutInMinutes') ? outboundRule.idleTimeoutInMinutes : 4 + } +}] + +var probes_var = [for probe in probes: { + name: probe.name + properties: { + protocol: contains(probe, 'protocol') ? probe.protocol : 'Tcp' + requestPath: (contains(probe, 'protocol') && toLower(probe.protocol) == 'tcp') ? null : probe.requestPath + port: contains(probe, 'port') ? probe.port : 80 + intervalInSeconds: contains(probe, 'intervalInSeconds') ? probe.intervalInSeconds : 5 + numberOfProbes: contains(probe, 'numberOfProbes') ? probe.numberOfProbes : 2 + } +}] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: loadBalancerSku + } + properties: { + frontendIPConfigurations: frontendIPConfigurations_var + backendAddressPools: backendAddressPools + loadBalancingRules: loadBalancingRules_var + outboundRules: outboundRules_var + probes: probes_var + } +} + +module loadBalancer_backendAddressPools 'backendAddressPools/deploy.bicep' = [for (backendAddressPool, index) in backendAddressPools: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-backendAddressPools-${index}' + params: { + loadBalancerName: loadBalancer.name + name: backendAddressPool.name + loadBalancerBackendAddresses: contains(backendAddressPool, 'loadBalancerBackendAddresses') ? backendAddressPool.loadBalancerBackendAddresses : [] + tunnelInterfaces: contains(backendAddressPool, 'tunnelInterfaces') ? backendAddressPool.tunnelInterfaces : [] + } +}] + +module loadBalancer_inboundNATRules 'inboundNatRules/deploy.bicep' = [for (inboundNATRule, index) in inboundNatRules: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-inboundNatRules-${index}' + params: { + loadBalancerName: loadBalancer.name + name: inboundNATRule.name + frontendIPConfigurationName: inboundNATRule.frontendIPConfigurationName + frontendPort: inboundNATRule.frontendPort + backendPort: contains(inboundNATRule, 'backendPort') ? inboundNATRule.backendPort : inboundNATRule.frontendPort + backendAddressPoolName: contains(inboundNATRule, 'backendAddressPoolName') ? inboundNATRule.backendAddressPoolName : '' + enableFloatingIP: contains(inboundNATRule, 'enableFloatingIP') ? inboundNATRule.enableFloatingIP : false + enableTcpReset: contains(inboundNATRule, 'enableTcpReset') ? inboundNATRule.enableTcpReset : false + frontendPortRangeEnd: contains(inboundNATRule, 'frontendPortRangeEnd') ? inboundNATRule.frontendPortRangeEnd : -1 + frontendPortRangeStart: contains(inboundNATRule, 'frontendPortRangeStart') ? inboundNATRule.frontendPortRangeStart : -1 + idleTimeoutInMinutes: contains(inboundNATRule, 'idleTimeoutInMinutes') ? inboundNATRule.idleTimeoutInMinutes : 4 + protocol: contains(inboundNATRule, 'protocol') ? inboundNATRule.protocol : 'Tcp' + } + dependsOn: [ + loadBalancer_backendAddressPools + ] +}] + +resource loadBalancer_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${loadBalancer.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: loadBalancer +} + +resource loadBalancer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${loadBalancer.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: loadBalancer +} + +module loadBalancer_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: loadBalancer.id + } +}] + +@description('The name of the load balancer') +output name string = loadBalancer.name + +@description('The resource ID of the load balancer') +output resourceId string = loadBalancer.id + +@description('The resource group the load balancer was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep new file mode 100644 index 000000000..6c7da8f4f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep @@ -0,0 +1,90 @@ +@description('Required. The name of the parent load balancer') +param loadBalancerName string + +@description('Required. The name of the inbound NAT rule') +param name string + +@description('Required. The port for the external endpoint. Port numbers for each rule must be unique within the Load Balancer. ') +@minValue(1) +@maxValue(65534) +param frontendPort int + +@description('Optional. The port used for the internal endpoint.') +@minValue(1) +@maxValue(65535) +param backendPort int = frontendPort + +@description('Optional. Name of the backend address pool') +param backendAddressPoolName string = '' + +@description('Optional. Configures a virtual machine\'s endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. This setting can\'t be changed after you create the endpoint.') +param enableFloatingIP bool = false + +@description('Optional. Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. This element is only used when the protocol is set to TCP.') +param enableTcpReset bool = false + +@description('Required. The name of the frontend IP address to set for the inbound NAT rule') +param frontendIPConfigurationName string + +@description('Optional. The port range end for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeStart. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool.') +@minValue(-1) +@maxValue(65534) +param frontendPortRangeEnd int = -1 + +@description('Optional. The port range start for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeEnd. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool.') +@minValue(-1) +@maxValue(65534) +param frontendPortRangeStart int = -1 + +@description('Optional. The timeout for the TCP idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP.') +param idleTimeoutInMinutes int = 4 + +@description('Optional. The transport protocol for the endpoint.') +@allowed([ + 'All' + 'Tcp' + 'Udp' +]) +param protocol string = 'Tcp' + +@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 loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: loadBalancerName +} + +resource inboundNatRule 'Microsoft.Network/loadBalancers/inboundNatRules@2021-05-01' = { + name: name + properties: { + frontendPort: frontendPort + backendPort: backendPort + backendAddressPool: !empty(backendAddressPoolName) ? { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, backendAddressPoolName) + } : null + enableFloatingIP: enableFloatingIP + enableTcpReset: enableTcpReset + frontendIPConfiguration: { + id: '${loadBalancer.id}/frontendIPConfigurations/${frontendIPConfigurationName}' + } + frontendPortRangeStart: frontendPortRangeStart != -1 ? frontendPortRangeStart : null + frontendPortRangeEnd: frontendPortRangeEnd != -1 ? frontendPortRangeEnd : null + idleTimeoutInMinutes: idleTimeoutInMinutes + protocol: protocol + } + parent: loadBalancer +} + +@description('The name of the inbound NAT rule') +output name string = inboundNatRule.name + +@description('The resource ID of the inbound NAT rule') +output resourceId string = inboundNatRule.id + +@description('The resource group the inbound NAT rule was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/readme.md b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/readme.md new file mode 100644 index 000000000..644da6d40 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/readme.md @@ -0,0 +1,39 @@ +# Load Balancer Inbound NAT Rules `[Microsoft.Network/loadBalancers/inboundNatRules]` + +This module deploys load balancers inbound NAT rules. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/loadBalancers/inboundNatRules` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backendAddressPoolName` | string | | | Optional. Name of the backend address pool | +| `backendPort` | int | `[parameters('frontendPort')]` | | Optional. The port used for the internal endpoint. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enableFloatingIP` | bool | | | Optional. Configures a virtual machine's endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. This setting can't be changed after you create the endpoint. | +| `enableTcpReset` | bool | | | Optional. Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. This element is only used when the protocol is set to TCP. | +| `frontendIPConfigurationName` | string | | | Required. The name of the frontend IP address to set for the inbound NAT rule | +| `frontendPort` | int | | | Required. The port for the external endpoint. Port numbers for each rule must be unique within the Load Balancer. | +| `frontendPortRangeEnd` | int | `-1` | | Optional. The port range end for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeStart. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool. | +| `frontendPortRangeStart` | int | `-1` | | Optional. The port range start for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeEnd. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool. | +| `idleTimeoutInMinutes` | int | `4` | | Optional. The timeout for the TCP idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP. | +| `loadBalancerName` | string | | | Required. The name of the parent load balancer | +| `name` | string | | | Required. The name of the inbound NAT rule | +| `protocol` | string | `Tcp` | `[All, Tcp, Udp]` | Optional. The transport protocol for the endpoint. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the inbound NAT rule | +| `resourceGroupName` | string | The resource group the inbound NAT rule was deployed into | +| `resourceId` | string | The resource ID of the inbound NAT rule | + +## Template references + +- [Loadbalancers/Inboundnatrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/inboundNatRules) diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/version.json b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/inboundNatRules/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/carml/1.0.0/Microsoft.Network/loadBalancers/readme.md b/carml/1.0.0/Microsoft.Network/loadBalancers/readme.md new file mode 100644 index 000000000..462bf1d2d --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/readme.md @@ -0,0 +1,224 @@ +# Load Balancers `[Microsoft.Network/loadBalancers]` + +This module deploys a load balancer. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/loadBalancers` | 2021-05-01 | +| `Microsoft.Network/loadBalancers/backendAddressPools` | 2021-05-01 | +| `Microsoft.Network/loadBalancers/inboundNatRules` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backendAddressPools` | _[backendAddressPools](backendAddressPools/readme.md)_ array | `[]` | | Optional. Collection of backend address pools used by a load balancer. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `frontendIPConfigurations` | array | | | Required. Array of objects containing all frontend IP configurations | +| `inboundNatRules` | _[inboundNatRules](inboundNatRules/readme.md)_ array | `[]` | | Optional. Collection of inbound NAT Rules used by a load balancer. Defining inbound NAT rules on your load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. They have to reference individual inbound NAT rules. | +| `loadBalancerSku` | string | `Standard` | `[Basic, Standard]` | Optional. Name of a load balancer SKU. | +| `loadBalancingRules` | array | `[]` | | Optional. Array of objects containing all load balancing rules | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The Proximity Placement Groups Name | +| `outboundRules` | array | `[]` | | Optional. The outbound rules. | +| `probes` | array | `[]` | | Optional. Array of objects containing all probes, these are references in the load balancing rules | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `frontendIPConfigurations` + +```json +"frontendIPConfigurations": { + "value": [ + { + "name": "p_hub-bfw-server-feip", + "properties": { + "publicIPAddressId": "[reference(variables('deploymentPIP-VPN')).outputs.publicIPAddressResourceId.value]", + "subnetId": "", + "privateIPAddress": "" + } + } + ] +} +``` + +### Parameter Usage: `backendAddressPools` + +```json +"backendAddressPools": { + "value": [ + { + "name": "p_hub-bfw-server-bepool", + "properties": { + "loadBalancerBackendAddresses": [ + { + "name": "iacs-sh-main-pd-01-euw-rg-network_awefwa01p-nic-int-01ipconfig-internal", + "properties": { + "virtualNetwork": { + "id": "[reference(variables('deploymentVNET')).outputs.vNetResourceId.value]" + }, + "ipAddress": "172.22.232.5" + } + }, + { + "name": "iacs-sh-main-pd-01-euw-rg-network_awefwa01p-ha-nic-int-01ipconfig-internal", + "properties": { + "virtualNetwork": { + "id": "[reference(variables('deploymentVNET')).outputs.vNetResourceId.value]" + }, + "ipAddress": "172.22.232.6" + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `loadBalancingRules` + +```json +"loadBalancingRules": { +"value": [ + { + "name": "p_hub-bfw-server-IPSEC-IKE-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 500, + "backendPort": 500, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-IPSEC-NATT-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 4500, + "backendPort": 4500, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-TINA-UDP-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 691, + "backendPort": 691, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-TINA-TCP-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Tcp", + "frontendPort": 691, + "backendPort": 691, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + } +] +} +``` + +### Parameter Usage: `probes` + +```json +"probes": { + "value": [ + { + "name": "p_hub-bfw-server-tcp-65001-probe", + "properties": { + "protocol": "Tcp", + "port": 65001, + "intervalInSeconds": 5, + "numberOfProbes": 2 + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the load balancer | +| `resourceGroupName` | string | The resource group the load balancer was deployed into | +| `resourceId` | string | The resource ID of the load balancer | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Loadbalancers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers) +- [Loadbalancers/Backendaddresspools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/backendAddressPools) +- [Loadbalancers/Inboundnatrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/inboundNatRules) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/loadBalancers/version.json b/carml/1.0.0/Microsoft.Network/loadBalancers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/loadBalancers/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/carml/1.0.0/Microsoft.Network/localNetworkGateways/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/localNetworkGateways/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/localNetworkGateways/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..dfc653e0a --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(localNetworkGateway.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: localNetworkGateway +}] diff --git a/carml/1.0.0/Microsoft.Network/localNetworkGateways/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/localNetworkGateways/.parameters/parameters.json new file mode 100644 index 000000000..878777fb1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/localNetworkGateways/.parameters/parameters.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lng-x-001" + }, + "localAddressPrefixes": { + "value": [ + "192.168.1.0/24" + ] + }, + "localGatewayPublicIpAddress": { + "value": "8.8.8.8" + }, + "localAsn": { + "value": "65123" + }, + "localBgpPeeringAddress": { + "value": "192.168.1.5" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/localNetworkGateways/deploy.bicep b/carml/1.0.0/Microsoft.Network/localNetworkGateways/deploy.bicep new file mode 100644 index 000000000..71af3d56e --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/localNetworkGateways/deploy.bicep @@ -0,0 +1,93 @@ +@description('Required. Name of the Local Network Gateway') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. List of the local (on-premises) IP address ranges') +param localAddressPrefixes array + +@description('Required. Public IP of the local gateway') +param localGatewayPublicIpAddress string + +@description('Optional. The BGP speaker\'s ASN. Not providing this value will automatically disable BGP on this Local Network Gateway resource.') +param localAsn string = '' + +@description('Optional. The BGP peering address and BGP identifier of this BGP speaker. Not providing this value will automatically disable BGP on this Local Network Gateway resource.') +param localBgpPeeringAddress string = '' + +@description('Optional. The weight added to routes learned from this BGP speaker. This will only take effect if both the localAsn and the localBgpPeeringAddress values are provided.') +param localPeerWeight string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. FQDN of local network gateway.') +param fqdn string = '' + +var bgpSettings = { + asn: localAsn + bgpPeeringAddress: localBgpPeeringAddress + peerWeight: !empty(localPeerWeight) ? localPeerWeight : '0' +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-08-01' = { + name: name + location: location + tags: tags + properties: { + localNetworkAddressSpace: { + addressPrefixes: localAddressPrefixes + } + fqdn: !empty(fqdn) ? fqdn : null + gatewayIpAddress: localGatewayPublicIpAddress + bgpSettings: !empty(localAsn) && !empty(localBgpPeeringAddress) ? bgpSettings : null + } +} + +resource localNetworkGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${localNetworkGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: localNetworkGateway +} + +module localNetworkGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LocalNetworkGateway-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: localNetworkGateway.id + } +}] + +@description('The resource ID of the local network gateway') +output resourceId string = localNetworkGateway.id + +@description('The resource group the local network gateway was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the local network gateway') +output name string = localNetworkGateway.name diff --git a/carml/1.0.0/Microsoft.Network/localNetworkGateways/readme.md b/carml/1.0.0/Microsoft.Network/localNetworkGateways/readme.md new file mode 100644 index 000000000..211fcdac8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/localNetworkGateways/readme.md @@ -0,0 +1,81 @@ +# Local Network Gateways `[Microsoft.Network/localNetworkGateways]` + +This module deploys a local network gateway. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/localNetworkGateways` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `fqdn` | string | | | Optional. FQDN of local network gateway. | +| `localAddressPrefixes` | array | | | Required. List of the local (on-premises) IP address ranges | +| `localAsn` | string | | | Optional. The BGP speaker's ASN. Not providing this value will automatically disable BGP on this Local Network Gateway resource. | +| `localBgpPeeringAddress` | string | | | Optional. The BGP peering address and BGP identifier of this BGP speaker. Not providing this value will automatically disable BGP on this Local Network Gateway resource. | +| `localGatewayPublicIpAddress` | string | | | Required. Public IP of the local gateway | +| `localPeerWeight` | string | | | Optional. The weight added to routes learned from this BGP speaker. This will only take effect if both the localAsn and the localBgpPeeringAddress values are provided. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the Local Network Gateway | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the local network gateway | +| `resourceGroupName` | string | The resource group the local network gateway was deployed into | +| `resourceId` | string | The resource ID of the local network gateway | + +## Template references + +- [Localnetworkgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/localNetworkGateways) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/localNetworkGateways/version.json b/carml/1.0.0/Microsoft.Network/localNetworkGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/localNetworkGateways/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/carml/1.0.0/Microsoft.Network/natGateways/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/natGateways/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/natGateways/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..dd5e86935 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(natGateway.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: natGateway +}] diff --git a/carml/1.0.0/Microsoft.Network/natGateways/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/natGateways/.parameters/parameters.json new file mode 100644 index 000000000..6f5ac729c --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/natGateways/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ngw-x-001" + }, + "natGatewayPublicIpAddress": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/natGateways/deploy.bicep b/carml/1.0.0/Microsoft.Network/natGateways/deploy.bicep new file mode 100644 index 000000000..aa5000019 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/natGateways/deploy.bicep @@ -0,0 +1,202 @@ +@description('Required. Name of the Azure Bastion resource') +param name string + +@description('Optional. The idle timeout of the nat gateway.') +param idleTimeoutInMinutes int = 5 + +@description('Optional. Use to have a new Public IP Address created for the NAT Gateway.') +param natGatewayPublicIpAddress bool = false + +@description('Optional. Specifies the name of the Public IP used by the NAT Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the Bastion\'s name.') +param natGatewayPipName string = '' + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param natGatewayPublicIPPrefixId string = '' + +@description('Optional. DNS name of the Public IP resource. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com') +param natGatewayDomainNameLabel string = '' + +@description('Optional. Existing Public IP Address resource names to use for the NAT Gateway.') +param publicIpAddresses array = [] + +@description('Optional. Existing Public IP Prefixes resource names to use for the NAT Gateway.') +param publicIpPrefixes array = [] + +@description('Optional. A list of availability zones denoting the zone in which Nat Gateway should be deployed.') +param zones array = [] + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param logsToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var natGatewayPipName_var = (empty(natGatewayPipName) ? '${name}-pip' : natGatewayPipName) +var natGatewayPublicIPPrefix = { + id: natGatewayPublicIPPrefixId +} + +var natGatewayPropertyPublicIPPrefixes = [for publicIpPrefix in publicIpPrefixes: { + id: az.resourceId('Microsoft.Network/publicIPPrefixes', publicIpPrefix) +}] +var natGatewayPropertyPublicIPAddresses = [for publicIpAddress in publicIpAddresses: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', publicIpAddress) +}] +var natGatewayProperties = { + idleTimeoutInMinutes: idleTimeoutInMinutes + publicIpPrefixes: natGatewayPropertyPublicIPPrefixes + publicIpAddresses: natGatewayPropertyPublicIPAddresses +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +// PUBLIC IP +// ========= +resource publicIP 'Microsoft.Network/publicIPAddresses@2021-05-01' = if (natGatewayPublicIpAddress) { + name: natGatewayPipName_var + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: { + publicIPAllocationMethod: 'Static' + publicIPPrefix: !empty(natGatewayPublicIPPrefixId) ? natGatewayPublicIPPrefix : null + dnsSettings: !empty(natGatewayDomainNameLabel) ? json('{"domainNameLabel": "${natGatewayDomainNameLabel}"}') : null + } +} + +resource publicIP_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIP.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIP +} + +resource publicIP_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${publicIP.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIP +} + +// NAT GATEWAY +// =========== +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: natGatewayProperties + zones: zones +} + +resource natGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${natGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: natGateway +} + +module natGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NatGateway-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: natGateway.id + } +}] + +@description('The name of the NAT Gateway') +output name string = natGateway.name + +@description('The resource ID of the NAT Gateway') +output resourceId string = natGateway.id + +@description('The resource group the NAT Gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/natGateways/readme.md b/carml/1.0.0/Microsoft.Network/natGateways/readme.md new file mode 100644 index 000000000..c96317f11 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/natGateways/readme.md @@ -0,0 +1,94 @@ +# NAT Gateways `[Microsoft.Network/natGateways]` + +This module deploys a NAT gateway. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/natGateways` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `idleTimeoutInMinutes` | int | `5` | | Optional. The idle timeout of the nat gateway. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the Azure Bastion resource | +| `natGatewayDomainNameLabel` | string | | | Optional. DNS name of the Public IP resource. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com | +| `natGatewayPipName` | string | | | Optional. Specifies the name of the Public IP used by the NAT Gateway. If it's not provided, a '-pip' suffix will be appended to the Bastion's name. | +| `natGatewayPublicIpAddress` | bool | | | Optional. Use to have a new Public IP Address created for the NAT Gateway. | +| `natGatewayPublicIPPrefixId` | string | | | Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `publicIpAddresses` | array | `[]` | | Optional. Existing Public IP Address resource names to use for the NAT Gateway. | +| `publicIpPrefixes` | array | `[]` | | Optional. Existing Public IP Prefixes resource names to use for the NAT Gateway. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags for the resource. | +| `zones` | array | `[]` | | Optional. A list of availability zones denoting the zone in which Nat Gateway should be deployed. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT Gateway | +| `resourceGroupName` | string | The resource group the NAT Gateway was deployed into | +| `resourceId` | string | The resource ID of the NAT Gateway | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Natgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/natGateways) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/natGateways/version.json b/carml/1.0.0/Microsoft.Network/natGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/natGateways/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/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b01db6840 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,37 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkSecurityGroup.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: networkSecurityGroup +}] diff --git a/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json new file mode 100644 index 000000000..0070aa133 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-nsg-x-001" + }, + "networkSecurityGroupSecurityRules": { + "value": [ + { + "name": "Specific", + "properties": { + "description": "Tests specific IPs and ports", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8080", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + { + "name": "Ranges", + "properties": { + "description": "Tests Ranges", + "protocol": "*", + "access": "Allow", + "priority": 101, + "direction": "Inbound", + "sourcePortRanges": [ + "80", + "81" + ], + "destinationPortRanges": [ + "90", + "91" + ], + "sourceAddressPrefixes": [ + "10.0.0.0/16", + "10.1.0.0/16" + ], + "destinationAddressPrefixes": [ + "10.2.0.0/16", + "10.3.0.0/16" + ] + } + }, + { + "name": "Port_8082", + "properties": { + "description": "Allow inbound access on TCP 8082", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8082", + "access": "Allow", + "priority": 102, + "direction": "Inbound", + "sourceApplicationSecurityGroupIds": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + ], + "destinationApplicationSecurityGroupIds": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + ] + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/networkSecurityGroups/deploy.bicep b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/deploy.bicep new file mode 100644 index 000000000..92ef62422 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/deploy.bicep @@ -0,0 +1,133 @@ +@description('Required. Name of the Network Security Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed.') +param networkSecurityGroupSecurityRules array = [] + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the NSG resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +]) +param logsToEnable array = [ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + securityRules: [for nsgSecurityRule in networkSecurityGroupSecurityRules: { + name: nsgSecurityRule.name + properties: { + description: contains(nsgSecurityRule.properties, 'description') ? nsgSecurityRule.properties.description : '' + protocol: nsgSecurityRule.properties.protocol + sourcePortRange: contains(nsgSecurityRule.properties, 'sourcePortRange') ? nsgSecurityRule.properties.sourcePortRange : '' + destinationPortRange: contains(nsgSecurityRule.properties, 'destinationPortRange') ? nsgSecurityRule.properties.destinationPortRange : '' + sourceAddressPrefix: contains(nsgSecurityRule.properties, 'sourceAddressPrefix') ? nsgSecurityRule.properties.sourceAddressPrefix : '' + destinationAddressPrefix: contains(nsgSecurityRule.properties, 'destinationAddressPrefix') ? nsgSecurityRule.properties.destinationAddressPrefix : '' + access: nsgSecurityRule.properties.access + priority: int(nsgSecurityRule.properties.priority) + direction: nsgSecurityRule.properties.direction + sourcePortRanges: contains(nsgSecurityRule.properties, 'sourcePortRanges') ? nsgSecurityRule.properties.sourcePortRanges : null + destinationPortRanges: contains(nsgSecurityRule.properties, 'destinationPortRanges') ? nsgSecurityRule.properties.destinationPortRanges : null + sourceAddressPrefixes: contains(nsgSecurityRule.properties, 'sourceAddressPrefixes') ? nsgSecurityRule.properties.sourceAddressPrefixes : null + destinationAddressPrefixes: contains(nsgSecurityRule.properties, 'destinationAddressPrefixes') ? nsgSecurityRule.properties.destinationAddressPrefixes : null + sourceApplicationSecurityGroups: (contains(nsgSecurityRule.properties, 'sourceApplicationSecurityGroupIds') && (!empty(nsgSecurityRule.properties.sourceApplicationSecurityGroupIds))) ? concat([], array(json('{"id": "${nsgSecurityRule.properties.sourceApplicationSecurityGroupIds[0]}", "location": "${location}"}'))) : null + destinationApplicationSecurityGroups: (contains(nsgSecurityRule.properties, 'destinationApplicationSecurityGroupIds') && (!empty(nsgSecurityRule.properties.destinationApplicationSecurityGroupIds))) ? concat([], array(json('{"id": "${nsgSecurityRule.properties.destinationApplicationSecurityGroupIds[0]}", "location": "${location}"}'))) : null + } + }] + } +} + +resource networkSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkSecurityGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkSecurityGroup +} + +resource networkSecurityGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${networkSecurityGroup.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: networkSecurityGroup +} + +module networkSecurityGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NSG-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkSecurityGroup.id + } +}] + +@description('The resource group the network security group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the network security group') +output resourceId string = networkSecurityGroup.id + +@description('The name of the network security group') +output name string = networkSecurityGroup.name diff --git a/carml/1.0.0/Microsoft.Network/networkSecurityGroups/readme.md b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/readme.md new file mode 100644 index 000000000..93c865c62 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/readme.md @@ -0,0 +1,164 @@ +# Network Security Groups `[Microsoft.Network/networkSecurityGroups]` + +This template deploys a network security group (NSG) with optional security rules. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/networkSecurityGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | Optional. The name of logs that will be streamed. | +| `name` | string | | | Required. Name of the Network Security Group. | +| `networkSecurityGroupSecurityRules` | array | `[]` | | Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the NSG resource. | + +### Parameter Usage: `networkSecurityGroupSecurityRules` + +The `networkSecurityGroupSecurityRules` parameter accepts a JSON Array of `securityRule` to deploy to the Network Security Group (NSG). + +Note that in case of using ASGs (Application Security Groups) - `sourceApplicationSecurityGroupIds` and `destinationApplicationSecurityGroupIds` properties - both the NSG and the ASG(s) have to be in the same Azure region. Currently an NSG can only handle one source and one destination ASG. +Here's an example of specifying a couple security rules: + +```json +"networkSecurityGroupSecurityRules": { + "value": [ + { + "name": "Port_8080", + "properties": { + "description": "Allow inbound access on TCP 8080", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8080", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 100, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [], + "sourceApplicationSecurityGroupIds": [], + "destinationApplicationSecurityGroupIds": [] + } + }, + { + "name": "Port_8081", + "properties": { + "description": "Allow inbound access on TCP 8081", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8081", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 101, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [], + "sourceApplicationSecurityGroupIds": [], + "destinationApplicationSecurityGroupIds": [] + } + }, + { + "name": "Port_8082", + "properties": { + "description": "Allow inbound access on TCP 8082", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8082", + "sourceAddressPrefix": "", + "destinationAddressPrefix": "", + "access": "Allow", + "priority": 102, + "direction": "Inbound", + "sourcePortRanges": [], + "destinationPortRanges": [], + "sourceAddressPrefixes": [], + "destinationAddressPrefixes": [], + //sourceApplicationSecurityGroupIds currently only supports 1 ID ! + "sourceApplicationSecurityGroupIds": [ + "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/applicationSecurityGroups/" + ], + //destinationApplicationSecurityGroupIds currently only supports 1 ID ! + "destinationApplicationSecurityGroupIds": [ + "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/applicationSecurityGroups/" + ] + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the network security group | +| `resourceGroupName` | string | The resource group the network security group was deployed into | +| `resourceId` | string | The resource ID of the network security group | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networksecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/networkSecurityGroups/version.json b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkSecurityGroups/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/carml/1.0.0/Microsoft.Network/networkWatchers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/networkWatchers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b2cac768e --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkWatcher.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: networkWatcher +}] diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/networkWatchers/.parameters/min.parameters.json new file mode 100644 index 000000000..78acbb0c7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "value": "northeurope" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/networkWatchers/.parameters/parameters.json new file mode 100644 index 000000000..78a7e1f27 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/.parameters/parameters.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "adp-<>-az-nw-x-001" + }, + "flowLogs": { + "value": [ + { + "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "enabled": false + }, + { + "name": "adp-<>-az-nsg-x-apgw-flowlog", + "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-apgw", + "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "formatVersion": 1, + "trafficAnalyticsInterval": 10, + "retentionInDays": 8 + } + ] + }, + "connectionMonitors": { + "value": [ + { + "name": "adp-<>-az-conn-mon-x-001", + "endpoints": [ + { + "name": "<>-az-subnet-x-001(validation-rg)", + "type": "AzureVM", + "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/virtualMachines/adp-<>-vm-01" + }, + { + "name": "Office Portal", + "type": "ExternalAddress", + "address": "www.office.com" + } + ], + "testConfigurations": [ + { + "name": "HTTP Test", + "testFrequencySec": 30, + "protocol": "Http", + "httpConfiguration": { + "port": 80, + "method": "Get", + "requestHeaders": [], + "validStatusCodeRanges": [ + "200" + ], + "preferHTTPS": false + }, + "successThreshold": { + "checksFailedPercent": 5, + "roundTripTimeMs": 100 + } + } + ], + "testGroups": [ + { + "name": "TestHTTPBing", + "disable": false, + "testConfigurations": [ + "HTTP Test" + ], + "sources": [ + "<>-az-subnet-x-001(validation-rg)" + ], + "destinations": [ + "Office Portal" + ] + } + ], + "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep b/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep new file mode 100644 index 000000000..542cca57f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep @@ -0,0 +1,66 @@ +@description('Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG') +param networkWatcherName string = 'NetworkWatcher_${resourceGroup().location}' + +@description('Optional. Name of the resource.') +param name string + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. List of connection monitor endpoints.') +param endpoints array = [] + +@description('Optional. List of connection monitor test configurations.') +param testConfigurations array = [] + +@description('Optional. List of connection monitor test groups.') +param testGroups array = [] + +@description('Optional. Specify the Log Analytics Workspace Resource ID') +param workspaceResourceId string = '' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var outputs = !empty(workspaceResourceId) ? [ + { + type: 'Workspace' + workspaceSettings: { + workspaceResourceId: workspaceResourceId + } + } +] : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: networkWatcherName +} + +resource connectionMonitor 'Microsoft.Network/networkWatchers/connectionMonitors@2021-05-01' = { + name: name + parent: networkWatcher + tags: tags + location: location + properties: { + endpoints: endpoints + testConfigurations: testConfigurations + testGroups: testGroups + outputs: outputs + } +} + +@description('The name of the deployed connection monitor') +output name string = connectionMonitor.name + +@description('The resource ID of the deployed connection monitor') +output resourceId string = connectionMonitor.id + +@description('The resource group the connection monitor was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/readme.md b/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/readme.md new file mode 100644 index 000000000..4bcf93a95 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/readme.md @@ -0,0 +1,52 @@ +# Network Watchers Connection Monitors `[Microsoft.Network/networkWatchers/connectionMonitors]` + +This template deploys Connection Monitors. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkWatchers/connectionMonitors` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `endpoints` | array | `[]` | | Optional. List of connection monitor endpoints. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | | | Optional. Name of the resource. | +| `networkWatcherName` | string | `[format('NetworkWatcher_{0}', resourceGroup().location)]` | | Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `testConfigurations` | array | `[]` | | Optional. List of connection monitor test configurations. | +| `testGroups` | array | `[]` | | Optional. List of connection monitor test groups. | +| `workspaceResourceId` | string | | | Optional. Specify the Log Analytics Workspace Resource ID | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed connection monitor | +| `resourceGroupName` | string | The resource group the connection monitor was deployed into | +| `resourceId` | string | The resource ID of the deployed connection monitor | + +## Template references + +- [Networkwatchers/Connectionmonitors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/connectionMonitors) diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/version.json b/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/connectionMonitors/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/carml/1.0.0/Microsoft.Network/networkWatchers/deploy.bicep b/carml/1.0.0/Microsoft.Network/networkWatchers/deploy.bicep new file mode 100644 index 000000000..9d6ab97fa --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/deploy.bicep @@ -0,0 +1,96 @@ +@description('Required. Name of the Network Watcher resource (hidden)') +@minLength(1) +param name string = 'NetworkWatcher_${location}' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array that contains the Connection Monitors') +param connectionMonitors array = [] + +@description('Optional. Array that contains the Flow Logs') +param flowLogs array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource networkWatcher_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkWatcher.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkWatcher +} + +module networkWatcher_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NW-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkWatcher.id + } +}] + +module networkWatcher_connectionMonitors 'connectionMonitors/deploy.bicep' = [for (connectionMonitor, index) in connectionMonitors: { + name: '${uniqueString(deployment().name, location)}-NW-ConnectionMonitor-${index}' + params: { + endpoints: contains(connectionMonitor, 'endpoints') ? connectionMonitor.endpoints : [] + name: connectionMonitor.name + networkWatcherName: networkWatcher.name + testConfigurations: contains(connectionMonitor, 'testConfigurations') ? connectionMonitor.testConfigurations : [] + testGroups: contains(connectionMonitor, 'testGroups') ? connectionMonitor.testGroups : [] + workspaceResourceId: contains(connectionMonitor, 'workspaceResourceId') ? connectionMonitor.workspaceResourceId : '' + } +}] + +module networkWatcher_flowLogs 'flowLogs/deploy.bicep' = [for (flowLog, index) in flowLogs: { + name: '${uniqueString(deployment().name, location)}-NW-FlowLog-${index}' + params: { + enabled: contains(flowLog, 'enabled') ? flowLog.enabled : true + formatVersion: contains(flowLog, 'formatVersion') ? flowLog.formatVersion : 2 + location: contains(flowLog, 'location') ? flowLog.location : location + name: contains(flowLog, 'name') ? flowLog.name : '${last(split(flowLog.targetResourceId, '/'))}-${split(flowLog.targetResourceId, '/')[4]}-flowlog' + networkWatcherName: networkWatcher.name + retentionInDays: contains(flowLog, 'retentionInDays') ? flowLog.retentionInDays : 365 + storageId: flowLog.storageId + targetResourceId: flowLog.targetResourceId + trafficAnalyticsInterval: contains(flowLog, 'trafficAnalyticsInterval') ? flowLog.trafficAnalyticsInterval : 60 + workspaceResourceId: contains(flowLog, 'workspaceResourceId') ? flowLog.workspaceResourceId : '' + } +}] + +@description('The name of the deployed network watcher') +output name string = networkWatcher.name + +@description('The resource ID of the deployed network watcher') +output resourceId string = networkWatcher.id + +@description('The resource group the network watcher was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep new file mode 100644 index 000000000..f022078b1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep @@ -0,0 +1,95 @@ +@description('Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG') +param networkWatcherName string = 'NetworkWatcher_${resourceGroup().location}' + +@description('Optional. Name of the resource.') +param name string = '${last(split(targetResourceId, '/'))}-${split(targetResourceId, '/')[4]}-flowlog' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Resource ID of the NSG that must be enabled for Flow Logs.') +param targetResourceId string + +@description('Required. Resource ID of the diagnostic storage account.') +param storageId string + +@description('Optional. If the flow log should be enabled') +param enabled bool = true + +@description('Optional. The flow log format version') +@allowed([ + 1 + 2 +]) +param formatVersion int = 2 + +@description('Optional. Specify the Log Analytics Workspace Resource ID') +param workspaceResourceId string = '' + +@description('Optional. The interval in minutes which would decide how frequently TA service should do flow analytics.') +@allowed([ + 10 + 60 +]) +param trafficAnalyticsInterval int = 60 + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param retentionInDays int = 365 + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var flowAnalyticsConfiguration = !empty(workspaceResourceId) && enabled == true ? { + networkWatcherFlowAnalyticsConfiguration: { + enabled: true + workspaceResourceId: workspaceResourceId + trafficAnalyticsInterval: trafficAnalyticsInterval + } +} : { + networkWatcherFlowAnalyticsConfiguration: { + enabled: false + } +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: networkWatcherName +} + +resource flowLog 'Microsoft.Network/networkWatchers/flowLogs@2021-05-01' = { + name: name + parent: networkWatcher + tags: tags + location: location + properties: { + targetResourceId: targetResourceId + storageId: storageId + enabled: enabled + retentionPolicy: { + days: retentionInDays + enabled: retentionInDays == 0 ? false : true + } + format: { + type: 'JSON' + version: formatVersion + } + flowAnalyticsConfiguration: flowAnalyticsConfiguration + } +} +@description('The name of the flow log') +output name string = flowLog.name + +@description('The resource ID of the flow log') +output resourceId string = flowLog.id + +@description('The resource group the flow log was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/readme.md b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/readme.md new file mode 100644 index 000000000..607b3c5e7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/readme.md @@ -0,0 +1,56 @@ +# NSG Flow Logs `[Microsoft.Network/networkWatchers/flowLogs]` + +This module controls the Network Security Group Flow Logs and analytics settings +**Note: this module must be run on the Resource Group where Network Watcher is deployed** + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkWatchers/flowLogs` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enabled` | bool | `True` | | Optional. If the flow log should be enabled | +| `formatVersion` | int | `2` | `[1, 2]` | Optional. The flow log format version | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | `[format('{0}-{1}-flowlog', last(split(parameters('targetResourceId'), '/')), split(parameters('targetResourceId'), '/')[4])]` | | Optional. Name of the resource. | +| `networkWatcherName` | string | `[format('NetworkWatcher_{0}', resourceGroup().location)]` | | Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG | +| `retentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `storageId` | string | | | Required. Resource ID of the diagnostic storage account. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `targetResourceId` | string | | | Required. Resource ID of the NSG that must be enabled for Flow Logs. | +| `trafficAnalyticsInterval` | int | `60` | `[10, 60]` | Optional. The interval in minutes which would decide how frequently TA service should do flow analytics. | +| `workspaceResourceId` | string | | | Optional. Specify the Log Analytics Workspace Resource ID | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the flow log | +| `resourceGroupName` | string | The resource group the flow log was deployed into | +| `resourceId` | string | The resource ID of the flow log | + +## Template references + +- [Networkwatchers/Flowlogs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/flowLogs) diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/version.json b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/flowLogs/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/carml/1.0.0/Microsoft.Network/networkWatchers/readme.md b/carml/1.0.0/Microsoft.Network/networkWatchers/readme.md new file mode 100644 index 000000000..243e9131e --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/readme.md @@ -0,0 +1,82 @@ +# Network Watchers `[Microsoft.Network/networkWatchers]` + +This template deploys a network watcher. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/networkWatchers` | 2021-05-01 | +| `Microsoft.Network/networkWatchers/connectionMonitors` | 2021-05-01 | +| `Microsoft.Network/networkWatchers/flowLogs` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `connectionMonitors` | _[connectionMonitors](connectionMonitors/readme.md)_ array | `[]` | | Optional. Array that contains the Connection Monitors | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `flowLogs` | _[flowLogs](flowLogs/readme.md)_ array | `[]` | | Optional. Array that contains the Flow Logs | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | `[format('NetworkWatcher_{0}', parameters('location'))]` | | Required. Name of the Network Watcher resource (hidden) | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed network watcher | +| `resourceGroupName` | string | The resource group the network watcher was deployed into | +| `resourceId` | string | The resource ID of the deployed network watcher | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networkwatchers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers) +- [Networkwatchers/Connectionmonitors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/connectionMonitors) +- [Networkwatchers/Flowlogs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/flowLogs) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/networkWatchers/version.json b/carml/1.0.0/Microsoft.Network/networkWatchers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/networkWatchers/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/carml/1.0.0/Microsoft.Network/privateDnsZones/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/privateDnsZones/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..9706c937b --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2018-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateDnsZone.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: privateDnsZone +}] diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/privateDnsZones/.parameters/parameters.json new file mode 100644 index 000000000..a69c73b84 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/.parameters/parameters.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-privdns-x-001.com" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "virtualNetworkLinks": { + "value": [ + { + "virtualNetworkResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001", + "registrationEnabled": true + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/deploy.bicep b/carml/1.0.0/Microsoft.Network/privateDnsZones/deploy.bicep new file mode 100644 index 000000000..7e38140e6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/deploy.bicep @@ -0,0 +1,75 @@ +@description('Required. Private DNS zone name.') +param name string + +@description('Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties \'vnetResourceId\' and \'registrationEnabled\'. The \'vnetResourceId\' is a resource ID of a vNet to link, \'registrationEnabled\' (bool) enables automatic DNS registration in the zone for the linked vNet.') +param virtualNetworkLinks array = [] + +@description('Optional. The location of the PrivateDNSZone. Should be global.') +param location string = 'global' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@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 privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: name + location: location + tags: tags +} + +module privateDnsZone_virtualNetworkLinks 'virtualNetworkLinks/deploy.bicep' = [for (virtualNetworkLinks, index) in virtualNetworkLinks: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-VirtualNetworkLink-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: contains(virtualNetworkLinks, 'name') ? virtualNetworkLinks.name : '${last(split(virtualNetworkLinks.virtualNetworkResourceId, '/'))}-vnetlink' + virtualNetworkResourceId: virtualNetworkLinks.virtualNetworkResourceId + location: contains(virtualNetworkLinks, 'location') ? virtualNetworkLinks.location : 'global' + registrationEnabled: contains(virtualNetworkLinks, 'registrationEnabled') ? virtualNetworkLinks.registrationEnabled : false + tags: contains(virtualNetworkLinks, 'tags') ? virtualNetworkLinks.tags : {} + } +}] + +resource privateDnsZone_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateDnsZone.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateDnsZone +} + +module privateDnsZone_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateDnsZone.id + } +}] + +@description('The resource group the private DNS zone was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the private DNS zone') +output name string = privateDnsZone.name + +@description('The resource ID of the private DNS zone') +output resourceId string = privateDnsZone.id diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/readme.md b/carml/1.0.0/Microsoft.Network/privateDnsZones/readme.md new file mode 100644 index 000000000..76894a628 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/readme.md @@ -0,0 +1,78 @@ +# Private DNS Zones `[Microsoft.Network/privateDnsZones]` + +This template deploys a private DNS zone. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateDnsZones` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | 2020-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `global` | | Optional. The location of the PrivateDNSZone. Should be global. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Private DNS zone name. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `virtualNetworkLinks` | _[virtualNetworkLinks](virtualNetworkLinks/readme.md)_ array | `[]` | | Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'vnetResourceId' and 'registrationEnabled'. The 'vnetResourceId' is a resource ID of a vNet to link, 'registrationEnabled' (bool) enables automatic DNS registration in the zone for the linked vNet. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private DNS zone | +| `resourceGroupName` | string | The resource group the private DNS zone was deployed into | +| `resourceId` | string | The resource ID of the private DNS zone | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privatednszones](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones) +- [Privatednszones/Virtualnetworklinks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/version.json b/carml/1.0.0/Microsoft.Network/privateDnsZones/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/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/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep new file mode 100644 index 000000000..220355de9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Optional. The name of the virtual network link.') +param name string = '${last(split(virtualNetworkResourceId, '/'))}-vnetlink' + +@description('Optional. The location of the PrivateDNSZone. Should be global.') +param location string = 'global' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?') +param registrationEnabled bool = false + +@description('Required. Link to another virtual network resource ID.') +param virtualNetworkResourceId string + +@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 privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource virtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { + name: name + parent: privateDnsZone + location: location + tags: tags + properties: { + registrationEnabled: registrationEnabled + virtualNetwork: { + id: virtualNetworkResourceId + } + } +} + +@description('The name of the deployed virtual network link') +output name string = virtualNetworkLink.name + +@description('The resource ID of the deployed virtual network link') +output resourceId string = virtualNetworkLink.id + +@description('The resource group of the deployed virtual network link') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md new file mode 100644 index 000000000..da5b3a590 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md @@ -0,0 +1,50 @@ +# Private DNS Zone Virtual Network Link `[Microsoft.Network/privateDnsZones/virtualNetworkLinks]` + +This module deploys private dns zone virtual network links. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | 2020-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `global` | | Optional. The location of the PrivateDNSZone. Should be global. | +| `name` | string | `[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]` | | Optional. The name of the virtual network link. | +| `privateDnsZoneName` | string | | | Required. Private DNS zone name. | +| `registrationEnabled` | bool | | | Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled? | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `virtualNetworkResourceId` | string | | | Required. Link to another virtual network resource ID. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed virtual network link | +| `resourceGroupName` | string | The resource group of the deployed virtual network link | +| `resourceId` | string | The resource ID of the deployed virtual network link | + +## Template references + +- [Privatednszones/Virtualnetworklinks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) diff --git a/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/version.json b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/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/carml/1.0.0/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep b/carml/1.0.0/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..78dbe685f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateEndpoint.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: privateEndpoint +}] diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json new file mode 100644 index 000000000..bfe13c34e --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pe-kvlt-min-001" + }, + "targetSubnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + }, + "serviceResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-pe" + }, + "groupId": { + "value": [ + "vault" + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/privateEndpoints/.parameters/parameters.json new file mode 100644 index 000000000..5b5f6f17b --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/.parameters/parameters.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pe-kvlt-001" + }, + "targetSubnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + }, + "serviceResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-pe" + }, + "groupId": { + "value": [ + "vault" + ] + }, + "privateDnsZoneGroups": { + "value": [ + { + "privateDNSResourceIds": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/deploy.bicep b/carml/1.0.0/Microsoft.Network/privateEndpoints/deploy.bicep new file mode 100644 index 000000000..1f506a757 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/deploy.bicep @@ -0,0 +1,96 @@ +@description('Required. Name of the private endpoint resource to create.') +param name string + +@description('Required. Resource ID of the subnet where the endpoint needs to be created.') +param targetSubnetResourceId string + +@description('Required. Resource ID of the resource that needs to be connected to the network.') +param serviceResourceId string + +@description('Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to.') +param groupId array + +@description('Optional. Array of Private DNS zone groups configuration on the private endpoint.') +param privateDnsZoneGroups array = [] + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags to be applied on all resources/resource groups in this deployment.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +module pid_cuaId '.bicep/nested_pid.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: serviceResourceId + groupIds: groupId + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: targetSubnetResourceId + } + customDnsConfigs: [] + } +} + +module privateEndpoint_privateDnsZoneGroups 'privateDnsZoneGroups/deploy.bicep' = [for (privateDnsZoneGroup, index) in privateDnsZoneGroups: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-PrivateDnsZoneGroup-${index}' + params: { + privateDNSResourceIds: privateDnsZoneGroup.privateDNSResourceIds + privateEndpointName: privateEndpoint.name + } +}] + +resource privateEndpoint_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateEndpoint.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateEndpoint +} + +module privateEndpoint_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateEndpoint.id + } +}] + +@description('The resource group the private endpoint was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the private endpoint') +output resourceId string = privateEndpoint.id + +@description('The name of the private endpoint') +output name string = privateEndpoint.name diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep new file mode 100644 index 000000000..94a0b29c9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep @@ -0,0 +1,44 @@ +@description('Required. The name of the private endpoint') +param privateEndpointName string + +@description('Required. List of private DNS resource IDs') +param privateDNSResourceIds array + +@description('Optional. The name of the private DNS Zone Group') +param name string = 'default' + +@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 privateDnsZoneConfigs = [for privateDNSResourceId in privateDNSResourceIds: { + name: privateEndpointName + properties: { + privateDnsZoneId: privateDNSResourceId + } +}] + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' existing = { + name: privateEndpointName +} + +resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = { + name: name + parent: privateEndpoint + properties: { + privateDnsZoneConfigs: privateDnsZoneConfigs + } +} + +@description('The name of the private endpoint DNS zone group') +output name string = privateDnsZoneGroup.name + +@description('The resource ID of the private endpoint DNS zone group') +output resourceId string = privateDnsZoneGroup.id + +@description('The resource group the private endpoint DNS zone group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md new file mode 100644 index 000000000..feb005806 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md @@ -0,0 +1,30 @@ +# Network Private Endpoint Private DNS Zone Group `[Microsoft.Network/privateEndpoints/privateDnsZoneGroups]` + +This module deploys a private endpoint private DNS zone group + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `default` | | Optional. The name of the private DNS Zone Group | +| `privateDNSResourceIds` | array | | | Required. List of private DNS resource IDs | +| `privateEndpointName` | string | | | Required. The name of the private endpoint | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private endpoint DNS zone group | +| `resourceGroupName` | string | The resource group the private endpoint DNS zone group was deployed into | +| `resourceId` | string | The resource ID of the private endpoint DNS zone group | + +## Template references + +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints/privateDnsZoneGroups) diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/version.json b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/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/carml/1.0.0/Microsoft.Network/privateEndpoints/readme.md b/carml/1.0.0/Microsoft.Network/privateEndpoints/readme.md new file mode 100644 index 000000000..45c3930cd --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/readme.md @@ -0,0 +1,91 @@ +# Private Endpoints `[Microsoft.Network/privateEndpoints]` + +This template deploys a private endpoint for a generic service. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource: + +- `PrivateDNSZone` +- `VirtualNetwork/subnet` +- The service that needs to be connected through private endpoint + +**Important**: Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `groupId` | array | | | Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the private endpoint resource to create. | +| `privateDnsZoneGroups` | _[privateDnsZoneGroups](privateDnsZoneGroups/readme.md)_ array | `[]` | | Optional. Array of Private DNS zone groups configuration on the private endpoint. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serviceResourceId` | string | | | Required. Resource ID of the resource that needs to be connected to the network. | +| `tags` | object | `{object}` | | Optional. Tags to be applied on all resources/resource groups in this deployment. | +| `targetSubnetResourceId` | string | | | Required. Resource ID of the subnet where the endpoint needs to be created. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private endpoint | +| `resourceGroupName` | string | The resource group the private endpoint was deployed into | +| `resourceId` | string | The resource ID of the private endpoint | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/privateEndpoints/version.json b/carml/1.0.0/Microsoft.Network/privateEndpoints/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/privateEndpoints/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/carml/1.0.0/Microsoft.Network/publicIPAddresses/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/publicIPAddresses/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPAddresses/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5d97a6277 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep @@ -0,0 +1,38 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: publicIpAddress +}] diff --git a/carml/1.0.0/Microsoft.Network/publicIPAddresses/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/publicIPAddresses/.parameters/parameters.json new file mode 100644 index 000000000..1e12e533b --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPAddresses/.parameters/parameters.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pip-x-001" + }, + "skuName": { + "value": "Standard" + }, + "publicIPAllocationMethod": { + "value": "Static" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/publicIPAddresses/deploy.bicep b/carml/1.0.0/Microsoft.Network/publicIPAddresses/deploy.bicep new file mode 100644 index 000000000..b7ccd8bbd --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPAddresses/deploy.bicep @@ -0,0 +1,182 @@ +@description('Required. The name of the Public IP Address') +param name string + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. The public IP address allocation method.') +@allowed([ + 'Dynamic' + 'Static' +]) +param publicIPAllocationMethod string = 'Dynamic' + +@description('Optional. Name of a public IP address SKU.') +@allowed([ + 'Basic' + 'Standard' +]) +param skuName string = 'Basic' + +@description('Optional. Tier of a public IP address SKU.') +@allowed([ + 'Global' + 'Regional' +]) +param skuTier string = 'Regional' + +@description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from.') +param zones array = [] + +@description('Optional. IP address version.') +@allowed([ + 'IPv4' + 'IPv6' +]) +param publicIPAddressVersion string = 'IPv4' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param logsToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIPPrefix = { + id: publicIPPrefixResourceId +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + zones: zones + properties: { + publicIPAddressVersion: publicIPAddressVersion + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + idleTimeoutInMinutes: 4 + ipTags: [] + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${publicIpAddress.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PIPAddress-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The resource group the public IP address was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address') +output resourceId string = publicIpAddress.id + +@description('The public IP address of the of the public IP address resource') +output ipAddress string = publicIpAddress.properties.ipAddress diff --git a/carml/1.0.0/Microsoft.Network/publicIPAddresses/readme.md b/carml/1.0.0/Microsoft.Network/publicIPAddresses/readme.md new file mode 100644 index 000000000..3c0e2eae8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPAddresses/readme.md @@ -0,0 +1,89 @@ +# Public IP Addresses `[Microsoft.Network/publicIPAddresses]` + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the Public IP Address | +| `publicIPAddressVersion` | string | `IPv4` | `[IPv4, IPv6]` | Optional. IP address version. | +| `publicIPAllocationMethod` | string | `Dynamic` | `[Dynamic, Static]` | Optional. The public IP address allocation method. | +| `publicIPPrefixResourceId` | string | | | Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuName` | string | `Basic` | `[Basic, Standard]` | Optional. Name of a public IP address SKU. | +| `skuTier` | string | `Regional` | `[Global, Regional]` | Optional. Tier of a public IP address SKU. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `zones` | array | `[]` | | Optional. A list of availability zones denoting the IP allocated for the resource needs to come from. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `ipAddress` | string | The public IP address of the of the public IP address resource | +| `name` | string | The name of the public IP address | +| `resourceGroupName` | string | The resource group the public IP address was deployed into | +| `resourceId` | string | The resource ID of the public IP address | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/publicIPAddresses/version.json b/carml/1.0.0/Microsoft.Network/publicIPAddresses/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPAddresses/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/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..a5ce0c854 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpPrefix.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: publicIpPrefix +}] diff --git a/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json new file mode 100644 index 000000000..5b4074820 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pippfx-x-001" + }, + "prefixLength": { + "value": 28 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/publicIPPrefixes/deploy.bicep b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/deploy.bicep new file mode 100644 index 000000000..64120a2eb --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/deploy.bicep @@ -0,0 +1,73 @@ +@description('Required. Name of the Public IP Prefix') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Length of the Public IP Prefix') +@minValue(28) +@maxValue(31) +param prefixLength int + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: { + publicIPAddressVersion: 'IPv4' + prefixLength: prefixLength + } +} + +resource publicIpPrefix_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpPrefix.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpPrefix +} + +module publicIpPrefix_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PIPPrefix-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpPrefix.id + } +}] + +@description('The resource ID of the public IP prefix') +output resourceId string = publicIpPrefix.id + +@description('The resource group the public IP prefix was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP prefix') +output name string = publicIpPrefix.name diff --git a/carml/1.0.0/Microsoft.Network/publicIPPrefixes/readme.md b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/readme.md new file mode 100644 index 000000000..ce588d4cb --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/readme.md @@ -0,0 +1,76 @@ +# Public IP Prefixes `[Microsoft.Network/publicIPPrefixes]` + +This template deploys a public IP prefix. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/publicIPPrefixes` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the Public IP Prefix | +| `prefixLength` | int | | | Required. Length of the Public IP Prefix | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the public IP prefix | +| `resourceGroupName` | string | The resource group the public IP prefix was deployed into | +| `resourceId` | string | The resource ID of the public IP prefix | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipprefixes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPPrefixes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Network/publicIPPrefixes/version.json b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/publicIPPrefixes/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/carml/1.0.0/Microsoft.Network/routeTables/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/routeTables/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/routeTables/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..162ee0f0a --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource routeTable 'Microsoft.Network/routeTables@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(routeTable.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: routeTable +}] diff --git a/carml/1.0.0/Microsoft.Network/routeTables/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/routeTables/.parameters/parameters.json new file mode 100644 index 000000000..edd5dba92 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/routeTables/.parameters/parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-udr-x-001" + }, + "routes": { + "value": [ + { + "name": "default", + "properties": { + "addressPrefix": "0.0.0.0/0", + "nextHopType": "VirtualAppliance", + "nextHopIpAddress": "172.16.0.20" + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/routeTables/deploy.bicep b/carml/1.0.0/Microsoft.Network/routeTables/deploy.bicep new file mode 100644 index 000000000..6712b2a98 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/routeTables/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. Name given for the hub route table.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. An Array of Routes to be established within the hub route table.') +param routes array = [] + +@description('Optional. Switch to disable BGP route propagation.') +param disableBgpRoutePropagation bool = false + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 routeTable 'Microsoft.Network/routeTables@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + routes: routes + disableBgpRoutePropagation: disableBgpRoutePropagation + } +} + +resource routeTable_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${routeTable.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: routeTable +} + +module routeTable_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RouteTable-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: routeTable.id + } +}] + +@description('The resource group the route table was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the route table') +output name string = routeTable.name + +@description('The resource ID of the route table') +output resourceId string = routeTable.id diff --git a/carml/1.0.0/Microsoft.Network/routeTables/readme.md b/carml/1.0.0/Microsoft.Network/routeTables/readme.md new file mode 100644 index 000000000..f880cc1af --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/routeTables/readme.md @@ -0,0 +1,119 @@ +# Route Tables `[Microsoft.Network/routeTables]` + +This module deploys a user defined route table. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/routeTables` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `disableBgpRoutePropagation` | bool | | | Optional. Switch to disable BGP route propagation. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name given for the hub route table. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `routes` | array | `[]` | | Optional. An Array of Routes to be established within the hub route table. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `routes` + +The `routes` parameter accepts a JSON Array of Route objects to deploy to the Route Table. + +Here's an example of specifying a few routes: + +```json +"routes": { + "value": [ + { + "name": "tojumpboxes", + "properties": { + "addressPrefix": "172.16.0.48/28", + "nextHopType": "VnetLocal" + } + }, + { + "name": "tosharedservices", + "properties": { + "addressPrefix": "172.16.0.64/27", + "nextHopType": "VnetLocal" + } + }, + { + "name": "toonprem", + "properties": { + "addressPrefix": "10.0.0.0/8", + "nextHopType": "VirtualNetworkGateway" + } + }, + { + "name": "tonva", + "properties": { + "addressPrefix": "172.16.0.0/18", + "nextHopType": "VirtualAppliance", + "nextHopIpAddress": "172.16.0.20" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the route table | +| `resourceGroupName` | string | The resource group the route table was deployed into | +| `resourceId` | string | The resource ID of the route table | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Routetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/routeTables) diff --git a/carml/1.0.0/Microsoft.Network/routeTables/version.json b/carml/1.0.0/Microsoft.Network/routeTables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/routeTables/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/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..22dfa6790 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource trafficmanagerprofile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(trafficmanagerprofile.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: trafficmanagerprofile +}] diff --git a/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json new file mode 100644 index 000000000..fd3469ed6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "tm-000001" + }, + "relativeName": { + "value": "tm-000001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/deploy.bicep b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/deploy.bicep new file mode 100644 index 000000000..f74ba3d9f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/deploy.bicep @@ -0,0 +1,179 @@ +@description('Required. Name of the Traffic Manager') +@minLength(1) +param name string + +@description('Optional. The status of the Traffic Manager profile.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param profileStatus string = 'Enabled' + +@description('Optional. The traffic routing method of the Traffic Manager profile.') +@allowed([ + 'Performance' + 'Priority' + 'Weighted' + 'Geographic' + 'MultiValue' + 'Subnet' +]) +param trafficRoutingMethod string = 'Performance' + +@description('Required. The relative DNS name provided by this Traffic Manager profile. This value is combined with the DNS domain name used by Azure Traffic Manager to form the fully-qualified domain name (FQDN) of the profile.') +param relativeName string + +@description('Optional. The DNS Time-To-Live (TTL), in seconds. This informs the local DNS resolvers and DNS clients how long to cache DNS responses provided by this Traffic Manager profile.') +param ttl int = 60 + +@description('Optional. The endpoint monitoring settings of the Traffic Manager profile.') +param monitorConfig object = { + protocol: 'http' + port: '80' + path: '/' +} + +@description('Optional. The list of endpoints in the Traffic Manager profile.') +param endpoints array = [] + +@description('Optional. Indicates whether Traffic View is \'Enabled\' or \'Disabled\' for the Traffic Manager profile. Null, indicates \'Disabled\'. Enabling this feature will increase the cost of the Traffic Manage profile.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param trafficViewEnrollmentStatus string = 'Disabled' + +@description('Optional. Maximum number of endpoints to be returned for MultiValue routing type.') +param maxReturn int = 1 + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ProbeHealthStatusEvents' +]) +param logsToEnable array = [ + 'ProbeHealthStatusEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' = { + name: name + tags: tags + location: 'global' + properties: { + profileStatus: profileStatus + trafficRoutingMethod: trafficRoutingMethod + dnsConfig: { + relativeName: relativeName + ttl: ttl + } + monitorConfig: monitorConfig + endpoints: endpoints + trafficViewEnrollmentStatus: trafficViewEnrollmentStatus + maxReturn: maxReturn + } +} + +resource trafficManagerProfile_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${trafficManagerProfile.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: trafficManagerProfile +} + +resource trafficManagerProfile_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${trafficManagerProfile.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: trafficManagerProfile +} + +module trafficManagerProfile_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name)}-TrafficManagerProfile-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: trafficManagerProfile.id + } +}] + +@description('The resource ID of the traffix manager') +output resourceId string = trafficManagerProfile.id + +@description('The resource group the traffix manager was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the traffix manager was deployed into') +output name string = trafficManagerProfile.name diff --git a/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/readme.md b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/readme.md new file mode 100644 index 000000000..d0d27ac79 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/readme.md @@ -0,0 +1,129 @@ +# Traffic Manager Profiles `[Microsoft.Network/trafficmanagerprofiles]` + +This module deploys a traffic manager profile. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/trafficmanagerprofiles` | 2018-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `endpoints` | array | `[]` | | Optional. The list of endpoints in the Traffic Manager profile. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ProbeHealthStatusEvents]` | `[ProbeHealthStatusEvents]` | Optional. The name of logs that will be streamed. | +| `maxReturn` | int | `1` | | Optional. Maximum number of endpoints to be returned for MultiValue routing type. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `monitorConfig` | object | `{object}` | | Optional. The endpoint monitoring settings of the Traffic Manager profile. | +| `name` | string | | | Required. Name of the Traffic Manager | +| `profileStatus` | string | `Enabled` | `[Enabled, Disabled]` | Optional. The status of the Traffic Manager profile. | +| `relativeName` | string | | | Required. The relative DNS name provided by this Traffic Manager profile. This value is combined with the DNS domain name used by Azure Traffic Manager to form the fully-qualified domain name (FQDN) of the profile. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Resource tags. | +| `trafficRoutingMethod` | string | `Performance` | `[Performance, Priority, Weighted, Geographic, MultiValue, Subnet]` | Optional. The traffic routing method of the Traffic Manager profile. | +| `trafficViewEnrollmentStatus` | string | `Disabled` | `[Disabled, Enabled]` | Optional. Indicates whether Traffic View is 'Enabled' or 'Disabled' for the Traffic Manager profile. Null, indicates 'Disabled'. Enabling this feature will increase the cost of the Traffic Manage profile. | +| `ttl` | int | `60` | | Optional. The DNS Time-To-Live (TTL), in seconds. This informs the local DNS resolvers and DNS clients how long to cache DNS responses provided by this Traffic Manager profile. | + +### Parameter Usage: `monitorConfig` + +```json +"monitorConfig": { + "value": + { + "protocol": "http", + "port": "80", + "path": "/" + } +} +``` + +### Parameter Usage: `endpoints` + +```json +"endpoints": { + "value": + [ + { + "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/trafficManagerProfiles//azureEndpoints/", + "name": "MyEndpoint001", + "type": "Microsoft.Network/trafficManagerProfiles/azureEndpoints", + "properties": + { + "endpointStatus": "Enabled", + "endpointMonitorStatus": "CheckingEndpoint", + "targetResourceId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/publicIPAddresses/", + "target": "my-pip-001.eastus.cloudapp.azure.com", + "weight": 1, + "priority": 1, + "endpointLocation": "East US" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the traffix manager was deployed into | +| `resourceGroupName` | string | The resource group the traffix manager was deployed into | +| `resourceId` | string | The resource ID of the traffix manager | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Trafficmanagerprofiles](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2018-08-01/trafficmanagerprofiles) diff --git a/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/version.json b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/trafficmanagerprofiles/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/carml/1.0.0/Microsoft.Network/virtualHubs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualHubs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/virtualHubs/.parameters/min.parameters.json new file mode 100644 index 000000000..dbe2fa650 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/.parameters/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": { + "name": { + "value": "<>-az-vhub-min-001" + }, + "addressPrefix": { + "value": "10.0.0.0/16" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/adp-<>-az-vw-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/virtualHubs/.parameters/parameters.json new file mode 100644 index 000000000..ed856582a --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/.parameters/parameters.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vhub-x-001" + }, + "addressPrefix": { + "value": "10.1.0.0/16" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/adp-<>-az-vw-x-001" + }, + "hubRouteTables": { + "value": [ + { + "name": "routeTable1" + } + ] + }, + "hubVirtualNetworkConnections": { + "value": [ + { + "name": "connection1", + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-vhub", + "routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vHub-x-001/hubRouteTables/routeTable1" + }, + "propagatedRouteTables": { + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vHub-x-001/hubRouteTables/routeTable1" + } + ], + "labels": [ + "none" + ] + } + } + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualHubs/deploy.bicep new file mode 100644 index 000000000..c7c743796 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/deploy.bicep @@ -0,0 +1,147 @@ +@description('Required. The virtual hub name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Required. Address-prefix for this VirtualHub.') +param addressPrefix string + +@description('Optional. Flag to control transit for VirtualRouter hub.') +param allowBranchToBranchTraffic bool = true + +@description('Optional. Resource ID of the Azure Firewall to link to') +param azureFirewallId string = '' + +@description('Optional. Resource ID of the Express Route Gateway to link to') +param expressRouteGatewayId string = '' + +@description('Optional. Resource ID of the Point-to-Site VPN Gateway to link to') +param p2SVpnGatewayId string = '' + +@description('Optional. The preferred routing gateway types') +@allowed([ + 'ExpressRoute' + 'None' + 'VpnGateway' + '' +]) +param preferredRoutingGateway string = '' + +@description('Optional. VirtualHub route tables') +param routeTableRoutes array = [] + +@description('Optional. ID of the Security Partner Provider to link to') +param securityPartnerProviderId string = '' + +@description('Optional. The Security Provider name.') +param securityProviderName string = '' + +@allowed([ + 'Basic' + 'Standard' +]) +@description('Optional. The sku of this VirtualHub.') +param sku string = 'Standard' + +@description('Optional. List of all virtual hub route table v2s associated with this VirtualHub.') +param virtualHubRouteTableV2s array = [] + +@description('Optional. VirtualRouter ASN.') +param virtualRouterAsn int = -1 + +@description('Optional. VirtualRouter IPs.') +param virtualRouterIps array = [] + +@description('Required. Resource ID of the virtual WAN to link to') +param virtualWanId string + +@description('Optional. Resource ID of the VPN Gateway to link to') +param vpnGatewayId string = '' + +@description('Optional. Route tables to create for the virtual hub.') +param hubRouteTables array = [] + +@description('Optional. Virtual network connections to create for the virtual hub.') +param hubVirtualNetworkConnections array = [] + +@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 virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressPrefix: addressPrefix + allowBranchToBranchTraffic: allowBranchToBranchTraffic + azureFirewall: !empty(azureFirewallId) ? { + id: azureFirewallId + } : null + expressRouteGateway: !empty(expressRouteGatewayId) ? { + id: expressRouteGatewayId + } : null + p2SVpnGateway: !empty(p2SVpnGatewayId) ? { + id: p2SVpnGatewayId + } : null + preferredRoutingGateway: !empty(preferredRoutingGateway) ? any(preferredRoutingGateway) : null + routeTable: !empty(routeTableRoutes) ? { + routes: routeTableRoutes + } : null + securityPartnerProvider: !empty(securityPartnerProviderId) ? { + id: securityPartnerProviderId + } : null + securityProviderName: securityProviderName + sku: sku + virtualHubRouteTableV2s: virtualHubRouteTableV2s + virtualRouterAsn: !(virtualRouterAsn == -1) ? virtualRouterAsn : null + virtualRouterIps: !empty(virtualRouterIps) ? virtualRouterIps : null + virtualWan: !empty(virtualWanId) ? { + id: virtualWanId + } : null + vpnGateway: !empty(vpnGatewayId) ? { + id: vpnGatewayId + } : null + } +} + +module virtualHub_routeTables 'hubRouteTables/deploy.bicep' = [for (routeTable, index) in hubRouteTables: { + name: '${uniqueString(deployment().name, location)}-routeTable-${index}' + params: { + virtualHubName: virtualHub.name + name: routeTable.name + labels: contains(routeTable, 'labels') ? routeTable.labels : [] + routes: contains(routeTable, 'routes') ? routeTable.routes : [] + } +}] + +module virtualHub_hubVirtualNetworkConnections 'hubVirtualNetworkConnections/deploy.bicep' = [for (virtualNetworkConnection, index) in hubVirtualNetworkConnections: { + name: '${uniqueString(deployment().name, location)}-connection-${index}' + params: { + virtualHubName: virtualHub.name + name: virtualNetworkConnection.name + enableInternetSecurity: contains(virtualNetworkConnection, 'enableInternetSecurity') ? virtualNetworkConnection.enableInternetSecurity : true + remoteVirtualNetworkId: virtualNetworkConnection.remoteVirtualNetworkId + routingConfiguration: contains(virtualNetworkConnection, 'routingConfiguration') ? virtualNetworkConnection.routingConfiguration : {} + } + dependsOn: [ + virtualHub_routeTables + ] +}] + +@description('The resource group the virtual hub was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual hub') +output resourceId string = virtualHub.id + +@description('The name of the virtual hub') +output name string = virtualHub.name diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep new file mode 100644 index 000000000..321da33b5 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep @@ -0,0 +1,41 @@ +@description('Required. The route table name.') +param name string + +@description('Required. The virtual hub name.') +param virtualHubName string + +@description('Optional. List of labels associated with this route table.') +param labels array = [] + +@description('Optional. List of all routes.') +param routes array = [] + +@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 virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' existing = { + name: virtualHubName +} + +resource hubRouteTable 'Microsoft.Network/virtualHubs/hubRouteTables@2021-05-01' = { + name: name + parent: virtualHub + properties: { + labels: !empty(labels) ? labels : null + routes: !empty(routes) ? routes : null + } +} + +@description('The name of the deployed virtual hub route table') +output name string = hubRouteTable.name + +@description('The resource ID of the deployed virtual hub route table') +output resourceId string = hubRouteTable.id + +@description('The resource group the virtual hub route table was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/readme.md b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/readme.md new file mode 100644 index 000000000..389844931 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/readme.md @@ -0,0 +1,31 @@ +# Virtual Hub Route Table `[Microsoft.Network/virtualHubs/hubRouteTables]` + +This module deploys virtual hub route tables. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs/hubRouteTables` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `labels` | array | `[]` | | Optional. List of labels associated with this route table. | +| `name` | string | | | Required. The route table name. | +| `routes` | array | `[]` | | Optional. List of all routes. | +| `virtualHubName` | string | | | Required. The virtual hub name. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed virtual hub route table | +| `resourceGroupName` | string | The resource group the virtual hub route table was deployed into | +| `resourceId` | string | The resource ID of the deployed virtual hub route table | + +## Template references + +- [Virtualhubs/Hubroutetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubRouteTables) diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/version.json b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubRouteTables/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/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep new file mode 100644 index 000000000..b45de46b7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep @@ -0,0 +1,47 @@ +@description('Required. The connection name.') +param name string + +@description('Required. The virtual hub name.') +param virtualHubName string + +@description('Optional. Enable internet security.') +param enableInternetSecurity bool = true + +@description('Required. Resource ID of the virtual network to link to') +param remoteVirtualNetworkId string + +@description('Optional. Routing Configuration indicating the associated and propagated route tables for this connection.') +param routingConfiguration object = {} + +@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 virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' existing = { + name: virtualHubName +} + +resource hubVirtualNetworkConnection 'Microsoft.Network/virtualHubs/hubVirtualNetworkConnections@2021-05-01' = { + name: name + parent: virtualHub + properties: { + enableInternetSecurity: enableInternetSecurity + remoteVirtualNetwork: { + id: remoteVirtualNetworkId + } + routingConfiguration: !empty(routingConfiguration) ? routingConfiguration : null + } +} + +@description('The resource group the virtual hub connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual hub connection') +output resourceId string = hubVirtualNetworkConnection.id + +@description('The name of the virtual hub connection') +output name string = hubVirtualNetworkConnection.name diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md new file mode 100644 index 000000000..80463970d --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md @@ -0,0 +1,36 @@ +# Virtual Hub Virtual Network Connections `[Microsoft.Network/virtualHubs/hubVirtualNetworkConnections]` + +This module deploys virtual hub virtual network connections. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enableInternetSecurity` | bool | `True` | | Optional. Enable internet security. | +| `name` | string | | | Required. The connection name. | +| `remoteVirtualNetworkId` | string | | | Required. Resource ID of the virtual network to link to | +| `routingConfiguration` | object | `{object}` | | Optional. Routing Configuration indicating the associated and propagated route tables for this connection. | +| `virtualHubName` | string | | | Required. The virtual hub name. | + +### Parameter Usage: `hubVirtualNetworkConnections` + +... + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual hub connection | +| `resourceGroupName` | string | The resource group the virtual hub connection was deployed into | +| `resourceId` | string | The resource ID of the virtual hub connection | + +## Template references + +- [Virtualhubs/Hubvirtualnetworkconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubVirtualNetworkConnections) diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/version.json b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/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/carml/1.0.0/Microsoft.Network/virtualHubs/readme.md b/carml/1.0.0/Microsoft.Network/virtualHubs/readme.md new file mode 100644 index 000000000..dc649408c --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/readme.md @@ -0,0 +1,68 @@ +# Virtual Hub `[Microsoft.Network/virtualHubs]` + +This module deploys a virtual hub. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs` | 2021-05-01 | +| `Microsoft.Network/virtualHubs/hubRouteTables` | 2021-05-01 | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefix` | string | | | Required. Address-prefix for this VirtualHub. | +| `allowBranchToBranchTraffic` | bool | `True` | | Optional. Flag to control transit for VirtualRouter hub. | +| `azureFirewallId` | string | | | Optional. Resource ID of the Azure Firewall to link to | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `expressRouteGatewayId` | string | | | Optional. Resource ID of the Express Route Gateway to link to | +| `hubRouteTables` | _[hubRouteTables](hubRouteTables/readme.md)_ array | `[]` | | Optional. Route tables to create for the virtual hub. | +| `hubVirtualNetworkConnections` | _[hubVirtualNetworkConnections](hubVirtualNetworkConnections/readme.md)_ array | `[]` | | Optional. Virtual network connections to create for the virtual hub. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `name` | string | | | Required. The virtual hub name. | +| `p2SVpnGatewayId` | string | | | Optional. Resource ID of the Point-to-Site VPN Gateway to link to | +| `preferredRoutingGateway` | string | | `[ExpressRoute, None, VpnGateway, ]` | Optional. The preferred routing gateway types | +| `routeTableRoutes` | array | `[]` | | Optional. VirtualHub route tables | +| `securityPartnerProviderId` | string | | | Optional. ID of the Security Partner Provider to link to | +| `securityProviderName` | string | | | Optional. The Security Provider name. | +| `sku` | string | `Standard` | `Basic`,`Standard` | Optional. The sku of this VirtualHub. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `virtualHubRouteTableV2s` | array | `[]` | | Optional. List of all virtual hub route table v2s associated with this VirtualHub. | +| `virtualRouterAsn` | int | `-1` | | Optional. VirtualRouter ASN. | +| `virtualRouterIps` | array | `[]` | | Optional. VirtualRouter IPs. | +| `virtualWanId` | string | | | Required. Resource ID of the virtual WAN to link to | +| `vpnGatewayId` | string | | | Optional. Resource ID of the VPN Gateway to link to | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual hub | +| `resourceGroupName` | string | The resource group the virtual hub was deployed into | +| `resourceId` | string | The resource ID of the virtual hub | + +## Template references + +- [Virtualhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs) +- [Virtualhubs/Hubroutetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubRouteTables) +- [Virtualhubs/Hubvirtualnetworkconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubVirtualNetworkConnections) diff --git a/carml/1.0.0/Microsoft.Network/virtualHubs/version.json b/carml/1.0.0/Microsoft.Network/virtualHubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualHubs/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/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d8188e9e6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualNetworkGateway.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: virtualNetworkGateway +}] diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json new file mode 100644 index 000000000..15f8bd233 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-gw-er-001" + }, + "gatewayPipName": { + "value": [ + "<>-az-gw-er-001-pip" + ] + }, + "domainNameLabel": { + "value": [ + "<>-az-gw-er-dm-001" + ] + }, + "virtualNetworkGatewayType": { + "value": "ExpressRoute" + }, + "virtualNetworkGatewaySku": { + "value": "ErGw1AZ" + }, + "vNetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "tags": { + "value": { + "Environment": "Validation", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "", + "CostCenter": "", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.parameters.json b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.parameters.json new file mode 100644 index 000000000..243053f3a --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.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": "<>-az-gw-vpn-001" + }, + "domainNameLabel": { + "value": [ + "<>-az-gw-vpn-dm-001" + ] + }, + "virtualNetworkGatewayType": { + "value": "Vpn" + }, + "virtualNetworkGatewaySku": { + "value": "VpnGw1AZ" + }, + "publicIpZones": { + "value": [ + "1" + ] + }, + "vpnType": { + "value": "RouteBased" + }, + "activeActive": { + "value": false + }, + "vNetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/deploy.bicep new file mode 100644 index 000000000..149119bae --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/deploy.bicep @@ -0,0 +1,387 @@ +@description('Required. Specifies the Virtual Network Gateway name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the name of the Public IP used by the Virtual Network Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the gateway\'s name.') +param gatewayPipName array = [] + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones.') +param publicIpZones array = [] + +@description('Optional. DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com') +param domainNameLabel array = [] + +@description('Required. Specifies the gateway type. E.g. VPN, ExpressRoute') +@allowed([ + 'Vpn' + 'ExpressRoute' +]) +param virtualNetworkGatewayType string + +@description('Required. The Sku of the Gateway.') +@allowed([ + 'Basic' + 'VpnGw1' + 'VpnGw2' + 'VpnGw3' + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'Standard' + 'HighPerformance' + 'UltraPerformance' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +]) +param virtualNetworkGatewaySku string + +@description('Required. Specifies the VPN type') +@allowed([ + 'PolicyBased' + 'RouteBased' +]) +param vpnType string = 'RouteBased' + +@description('Required. Virtual Network resource ID') +param vNetResourceId string + +@description('Optional. Value to specify if the Gateway should be deployed in active-active or active-passive configuration') +param activeActive bool = true + +@description('Optional. Value to specify if BGP is enabled or not') +param enableBgp bool = true + +@description('Optional. ASN value') +param asn int = 65815 + +@description('Optional. The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network.') +param vpnClientAddressPoolPrefix string = '' + +@description('Optional. Client root certificate data used to authenticate VPN clients.') +param clientRootCertData string = '' + +@description('Optional. Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet.') +param clientRevokedCertThumbprint string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param publicIpLogsToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'GatewayDiagnosticLog' + 'TunnelDiagnosticLog' + 'RouteDiagnosticLog' + 'IKEDiagnosticLog' + 'P2SDiagnosticLog' +]) +param virtualNetworkGatewayLogsToEnable array = [ + 'GatewayDiagnosticLog' + 'TunnelDiagnosticLog' + 'RouteDiagnosticLog' + 'IKEDiagnosticLog' + 'P2SDiagnosticLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var virtualNetworkGatewayDiagnosticsLogs = [for log in virtualNetworkGatewayLogsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] +var publicIpDiagnosticsLogs = [for log in publicIpLogsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var zoneRedundantSkus = [ + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'VpnGw4AZ' + 'VpnGw5AZ' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +] +var gatewayPipSku = contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? 'Standard' : 'Basic' +var gatewayPipAllocationMethod = contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? 'Static' : 'Dynamic' +var gatewaySubnetId = '${vNetResourceId}/subnets/GatewaySubnet' +var activeActive_var = virtualNetworkGatewayType == 'ExpressRoute' ? false : activeActive + +// Public IP variables +var gatewayPipName1 = length(gatewayPipName) == 0 ? '${name}-pip1' : gatewayPipName[0] +var gatewayPipName2 = activeActive_var ? (length(gatewayPipName) == 1 ? '${name}-pip2' : gatewayPipName[1]) : '' + +var gatewayMultiPipArray = [ + gatewayPipName1 + gatewayPipName2 +] +var gatewaySinglePipArray = [ + gatewayPipName1 +] +var virtualGatewayPipName_var = !empty(gatewayPipName2) ? gatewayMultiPipArray : gatewaySinglePipArray +var gatewayPipId1 = az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName1) +var gatewayPipId2 = activeActive_var ? az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName2) : az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName1) + +var enableBgp_var = virtualNetworkGatewayType == 'ExpressRoute' ? false : enableBgp +var vpnType_var = virtualNetworkGatewayType == 'ExpressRoute' ? 'PolicyBased' : vpnType +var bgpSettings = { + asn: asn +} +var publicIPPrefix = { + id: publicIPPrefixResourceId +} +var activePassiveIpConfiguration = [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: gatewaySubnetId + } + publicIPAddress: { + id: gatewayPipId1 + } + } + name: 'vNetGatewayConfig1' + } +] +var activeActiveIpConfiguration = [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: gatewaySubnetId + } + publicIPAddress: { + id: gatewayPipId1 + } + } + name: 'vNetGatewayConfig1' + } + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: gatewaySubnetId + } + publicIPAddress: { + id: gatewayPipId2 + } + } + name: 'vNetGatewayConfig2' + } +] +var vpnClientRootCertificates = [ + { + name: 'RootCert1' + properties: { + PublicCertData: clientRootCertData + } + } +] +var vpmClientRevokedCertificates = [ + { + name: 'RevokedCert1' + properties: { + Thumbprint: clientRevokedCertThumbprint + } + } +] +var vpnClientConfiguration = { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] + } + vpnClientRootCertificates: !empty(clientRootCertData) ? vpnClientRootCertificates : null + vpnClientRevokedCertificates: !empty(clientRevokedCertThumbprint) ? vpmClientRevokedCertificates : null +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +// Public IPs +// ========== +@batchSize(1) +resource virtualGatewayPublicIP 'Microsoft.Network/publicIPAddresses@2021-05-01' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: { + name: virtualGatewayPublicIpName + location: location + tags: tags + sku: { + name: gatewayPipSku + } + properties: { + publicIPAllocationMethod: gatewayPipAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + dnsSettings: length(virtualGatewayPipName_var) == length(domainNameLabel) ? { + domainNameLabel: domainNameLabel[index] + } : null + } + zones: contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? publicIpZones : null +}] + +@batchSize(1) +resource virtualGatewayPublicIP_lock 'Microsoft.Authorization/locks@2017-04-01' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: if (lock != 'NotSpecified') { + name: '${virtualGatewayPublicIpName}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualGatewayPublicIP[index] +}] + +@batchSize(1) +resource virtualNetworkGatewayPublicIp_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${virtualGatewayPublicIpName}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: publicIpDiagnosticsLogs + } + scope: virtualGatewayPublicIP[index] +}] + +// VNET Gateway +// ============ +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipConfigurations: activeActive_var ? activeActiveIpConfiguration : activePassiveIpConfiguration + activeActive: activeActive_var + enableBgp: enableBgp_var + bgpSettings: virtualNetworkGatewayType == 'ExpressRoute' ? null : bgpSettings + sku: { + name: virtualNetworkGatewaySku + tier: virtualNetworkGatewaySku + } + gatewayType: virtualNetworkGatewayType + vpnType: vpnType_var + vpnClientConfiguration: !empty(vpnClientAddressPoolPrefix) ? vpnClientConfiguration : null + } + dependsOn: [ + virtualGatewayPublicIP + ] +} + +resource virtualNetworkGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualNetworkGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualNetworkGateway +} + +resource virtualNetworkGateway_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${virtualNetworkGateway.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: virtualNetworkGatewayDiagnosticsLogs + } + scope: virtualNetworkGateway +} + +module virtualNetworkGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VNetGateway-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualNetworkGateway.id + } +}] + +@description('The resource group the virtual network gateway was deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network gateway') +output name string = virtualNetworkGateway.name + +@description('The resource ID of the virtual network gateway') +output resourceId string = virtualNetworkGateway.id + +@description('Shows if the virtual network gateway is configured in active-active mode') +output activeActive bool = virtualNetworkGateway.properties.activeActive diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/readme.md b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/readme.md new file mode 100644 index 000000000..247508810 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/readme.md @@ -0,0 +1,133 @@ +# Virtual Network Gateways `[Microsoft.Network/virtualNetworkGateways]` + +This module deploys a virtual network gateway. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | +| `Microsoft.Network/virtualNetworkGateways` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `activeActive` | bool | `True` | | Optional. Value to specify if the Gateway should be deployed in active-active or active-passive configuration | +| `asn` | int | `65815` | | Optional. ASN value | +| `clientRevokedCertThumbprint` | string | | | Optional. Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet. | +| `clientRootCertData` | string | | | Optional. Client root certificate data used to authenticate VPN clients. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `domainNameLabel` | array | `[]` | | Optional. DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com | +| `enableBgp` | bool | `True` | | Optional. Value to specify if BGP is enabled or not | +| `gatewayPipName` | array | `[]` | | Optional. Specifies the name of the Public IP used by the Virtual Network Gateway. If it's not provided, a '-pip' suffix will be appended to the gateway's name. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Specifies the Virtual Network Gateway name. | +| `publicIpLogsToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | Optional. The name of logs that will be streamed. | +| `publicIPPrefixResourceId` | string | | | Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `publicIpZones` | array | `[]` | | Optional. Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `virtualNetworkGatewayLogsToEnable` | array | `[GatewayDiagnosticLog, TunnelDiagnosticLog, RouteDiagnosticLog, IKEDiagnosticLog, P2SDiagnosticLog]` | `[GatewayDiagnosticLog, TunnelDiagnosticLog, RouteDiagnosticLog, IKEDiagnosticLog, P2SDiagnosticLog]` | Optional. The name of logs that will be streamed. | +| `virtualNetworkGatewaySku` | string | | `[Basic, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, VpnGw3AZ, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ]` | Required. The Sku of the Gateway. | +| `virtualNetworkGatewayType` | string | | `[Vpn, ExpressRoute]` | Required. Specifies the gateway type. E.g. VPN, ExpressRoute | +| `vNetResourceId` | string | | | Required. Virtual Network resource ID | +| `vpnClientAddressPoolPrefix` | string | | | Optional. The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network. | +| `vpnType` | string | `RouteBased` | `[PolicyBased, RouteBased]` | Required. Specifies the VPN type | + +### Parameter Usage: `subnets` + +The `subnets` parameter accepts a JSON Array of `subnet` objects to deploy to the Virtual Network. + +Here's an example of specifying a couple Subnets to deploy: + +```json +"subnets": { + "value": [ + { + "name": "app", + "properties": { + "addressPrefix": "10.1.0.0/24", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'app-nsg')]" + }, + "routeTable": { + "id": "[resourceId('Microsoft.Network/routeTables', 'app-udr')]" + } + } + }, + { + "name": "data", + "properties": { + "addressPrefix": "10.1.1.0/24" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `activeActive` | bool | Shows if the virtual network gateway is configured in active-active mode | +| `name` | string | The name of the virtual network gateway | +| `resourceGroupName` | string | The resource group the virtual network gateway was deployed | +| `resourceId` | string | The resource ID of the virtual network gateway | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworkgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworkGateways) diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/version.json b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworkGateways/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/carml/1.0.0/Microsoft.Network/virtualNetworks/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..bdc2ba0f0 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep @@ -0,0 +1,49 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualNetwork.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: virtualNetwork +}] diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json new file mode 100644 index 000000000..2d5064277 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-min-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/parameters.json new file mode 100644 index 000000000..8afa179ab --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/parameters.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-x-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + }, + "subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.255.0/24" + }, + { + "name": "<>-az-subnet-x-001", + "addressPrefix": "10.0.0.0/24", + "networkSecurityGroupName": "adp-<>-az-nsg-x-001", + "serviceEndpoints": [ + "Microsoft.EventHub", + "Microsoft.Sql", + "Microsoft.Storage", + "Microsoft.KeyVault" + ], + "routeTableName": "adp-<>-az-udr-x-001" + }, + { + "name": "<>-az-subnet-x-002", + "addressPrefix": "10.0.3.0/24", + "delegations": [ + { + "name": "netappDel", + "properties": { + "serviceName": "Microsoft.Netapp/volumes" + } + } + ] + }, + { + "name": "<>-az-subnet-x-003", + "addressPrefix": "10.0.6.0/24", + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json b/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json new file mode 100644 index 000000000..f8faae317 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-peer-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/24" + ] + }, + "subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.0.0/26" + } + ] + }, + "virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-peer01", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "useRemoteGateways": false, + "remotePeeringEnabled": true, + "remotePeeringName": "customName", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringAllowForwardedTraffic": true + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/deploy.bicep new file mode 100644 index 000000000..d01e8192d --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/deploy.bicep @@ -0,0 +1,229 @@ +@description('Required. The Virtual Network (vNet) Name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. An Array of 1 or more IP Address Prefixes for the Virtual Network.') +param addressPrefixes array + +@description('Optional. An Array of subnets to deploy to the Virtual Network.') +param subnets array = [] + +@description('Optional. DNS Servers associated to the Virtual Network.') +param dnsServers array = [] + +@description('Optional. Resource ID of the DDoS protection plan to assign the VNET to. If it\'s left blank, DDoS protection will not be configured. If it\'s provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription.') +param ddosProtectionPlanId string = '' + +@description('Optional. Virtual Network Peerings configurations') +param virtualNetworkPeerings array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'VMProtectionAlerts' +]) +param logsToEnable array = [ + 'VMProtectionAlerts' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var dnsServers_var = { + dnsServers: array(dnsServers) +} +var ddosProtectionPlan = { + id: ddosProtectionPlanId +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressSpace: { + addressPrefixes: addressPrefixes + } + ddosProtectionPlan: !empty(ddosProtectionPlanId) ? ddosProtectionPlan : null + dhcpOptions: !empty(dnsServers) ? dnsServers_var : null + enableDdosProtection: !empty(ddosProtectionPlanId) + subnets: [for subnet in subnets: { + name: subnet.name + properties: { + addressPrefix: subnet.addressPrefix + delegations: contains(subnet, 'delegations') ? subnet.delegations : null + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : null + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : null + } + }] + } +} + +@batchSize(1) +module virtualNetwork_subnets 'subnets/deploy.bicep' = [for (subnet, index) in subnets: { + name: '${uniqueString(deployment().name, location)}-subnet-${index}' + params: { + virtualNetworkName: virtualNetwork.name + name: subnet.name + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIpConfigurations: contains(subnet, 'applicationGatewayIpConfigurations') ? subnet.applicationGatewayIpConfigurations : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGatewayName: contains(subnet, 'natGatewayName') ? subnet.natGatewayName : '' + networkSecurityGroupName: contains(subnet, 'networkSecurityGroupName') ? subnet.networkSecurityGroupName : '' + networkSecurityGroupNameResourceGroupName: contains(subnet, 'networkSecurityGroupNameResourceGroupName') ? subnet.networkSecurityGroupNameResourceGroupName : resourceGroup().name + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : '' + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : '' + routeTableName: contains(subnet, 'routeTableName') ? subnet.routeTableName : '' + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + } +}] + +// Local to Remote peering +module virtualNetwork_peering_local 'virtualNetworkPeerings/deploy.bicep' = [for (peering, index) in virtualNetworkPeerings: { + name: '${uniqueString(deployment().name, location)}-vNetPeering-local-${index}' + params: { + localVnetName: name + remoteVirtualNetworkId: peering.remoteVirtualNetworkId + name: contains(peering, 'name') ? peering.name : '${name}-${last(split(peering.remoteVirtualNetworkId, '/'))}' + allowForwardedTraffic: contains(peering, 'allowForwardedTraffic') ? peering.allowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'allowGatewayTransit') ? peering.allowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'allowVirtualNetworkAccess') ? peering.allowVirtualNetworkAccess : true + doNotVerifyRemoteGateways: contains(peering, 'doNotVerifyRemoteGateways') ? peering.doNotVerifyRemoteGateways : true + useRemoteGateways: contains(peering, 'useRemoteGateways') ? peering.useRemoteGateways : false + } + dependsOn: [ + virtualNetwork_subnets + ] +}] + +// Remote to local peering (reverse) +module virtualNetwork_peering_remote 'virtualNetworkPeerings/deploy.bicep' = [for (peering, index) in virtualNetworkPeerings: if (contains(peering, 'remotePeeringEnabled') ? peering.remotePeeringEnabled == true : false) { + name: '${uniqueString(deployment().name, location)}-vNetPeering-remote-${index}' + scope: resourceGroup(split(peering.remoteVirtualNetworkId, '/')[2], split(peering.remoteVirtualNetworkId, '/')[4]) + params: { + localVnetName: last(split(peering.remoteVirtualNetworkId, '/')) + remoteVirtualNetworkId: virtualNetwork.id + name: contains(peering, 'remotePeeringName') ? peering.remotePeeringName : '${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}' + allowForwardedTraffic: contains(peering, 'remotePeeringAllowForwardedTraffic') ? peering.remotePeeringAllowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'remotePeeringAllowGatewayTransit') ? peering.remotePeeringAllowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'remotePeeringAllowVirtualNetworkAccess') ? peering.remotePeeringAllowVirtualNetworkAccess : true + doNotVerifyRemoteGateways: contains(peering, 'remotePeeringDoNotVerifyRemoteGateways') ? peering.remotePeeringDoNotVerifyRemoteGateways : true + useRemoteGateways: contains(peering, 'remotePeeringUseRemoteGateways') ? peering.remotePeeringUseRemoteGateways : false + } + dependsOn: [ + virtualNetwork_subnets + ] +}] + +resource virtualNetwork_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualNetwork.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualNetwork +} + +resource appServiceEnvironment_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${virtualNetwork.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: virtualNetwork +} + +module virtualNetwork_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VNet-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualNetwork.id + } +}] + +@description('The resource group the virtual network was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual network') +output resourceId string = virtualNetwork.id + +@description('The name of the virtual network') +output name string = virtualNetwork.name + +@description('The names of the deployed subnets') +output subnetNames array = [for subnet in subnets: subnet.name] + +@description('The resource IDs of the deployed subnets') +output subnetResourceIds array = [for subnet in subnets: az.resourceId('Microsoft.Network/virtualNetworks/subnets', name, subnet.name)] diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/readme.md b/carml/1.0.0/Microsoft.Network/virtualNetworks/readme.md new file mode 100644 index 000000000..d5a3d5ba0 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/readme.md @@ -0,0 +1,127 @@ +# Virtual Networks `[Microsoft.Network/virtualNetworks]` + +This template deploys a virtual network (vNet). + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/virtualNetworks` | 2021-05-01 | +| `Microsoft.Network/virtualNetworks/subnets` | 2021-05-01 | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefixes` | array | | | Required. An Array of 1 or more IP Address Prefixes for the Virtual Network. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `ddosProtectionPlanId` | string | | | Optional. Resource ID of the DDoS protection plan to assign the VNET to. If it's left blank, DDoS protection will not be configured. If it's provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `dnsServers` | array | `[]` | | Optional. DNS Servers associated to the Virtual Network. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[VMProtectionAlerts]` | `[VMProtectionAlerts]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The Virtual Network (vNet) Name. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `subnets` | _[subnets](subnets/readme.md)_ array | `[]` | | Optional. An Array of subnets to deploy to the Virtual Network. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `virtualNetworkPeerings` | _[virtualNetworkPeerings](virtualNetworkPeerings/readme.md)_ array | `[]` | | Optional. Virtual Network Peerings configurations | + +### Parameter Usage: `virtualNetworkPeerings` + +As the virtual network peering array allows you to deploy not only a one-way but also two-way peering (i.e reverse), you can use the following ***additional*** properties on top of what is documented in _[virtualNetworkPeerings](virtualNetworkPeerings/readme.md)_. + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `remotePeeringEnabled` | bool | `false` | | Optional. Set to true to also deploy the reverse peering for the configured remote virtual networks to the local network | +| `remotePeeringName` | string | `'${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}'` | | Optional. The Name of Vnet Peering resource. If not provided, default value will be - | +| `remotePeeringAllowForwardedTraffic` | bool | `true` | | Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. | +| `remotePeeringAllowGatewayTransit` | bool | `false` | | Optional. If gateway links can be used in remote virtual networking to link to this virtual network. | +| `remotePeeringAllowVirtualNetworkAccess` | bool | `true` | | Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. | +| `remotePeeringDoNotVerifyRemoteGateways` | bool | `true` | | Optional. If we need to verify the provisioning state of the remote gateway. | +| `remotePeeringUseRemoteGateways` | bool | `false` | | Optional. If remote gateways can be used on this virtual network. If the flag is set to `true`, and allowGatewayTransit on local peering is also `true`, virtual network will use gateways of local virtual network for transit. Only one peering can have this flag set to `true`. This flag cannot be set if virtual network already has a gateway. | + +### Parameter Usage: `addressPrefixes` + +The `addressPrefixes` parameter accepts a JSON Array of string values containing the IP Address Prefixes for the Virtual Network (vNet). + +Here's an example of specifying a single Address Prefix: + +```json +"addressPrefixes": { + "value": [ + "10.1.0.0/16" + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Considerations + +The network security group and route table resources must reside in the same resource group as the virtual network. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network | +| `resourceGroupName` | string | The resource group the virtual network was deployed into | +| `resourceId` | string | The resource ID of the virtual network | +| `subnetNames` | array | The names of the deployed subnets | +| `subnetResourceIds` | array | The resource IDs of the deployed subnets | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks) +- [Virtualnetworks/Subnets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/subnets) +- [Virtualnetworks/Virtualnetworkpeerings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/virtualNetworkPeerings) diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep new file mode 100644 index 000000000..53ac3a3ec --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep @@ -0,0 +1,128 @@ +@description('Optional. The Name of the subnet resource.') +param name string + +@description('Required. The name of the parent virtual network') +param virtualNetworkName string + +@description('Required. The address prefix for the subnet.') +param addressPrefix string + +@description('Optional. The network security group to assign to the subnet') +param networkSecurityGroupName string = '' + +@description('Optional. Resource Group where NSGs are deployed, if different than VNET Resource Group.') +@minLength(1) +param networkSecurityGroupNameResourceGroupName string = resourceGroup().name + +@description('Optional. The route table to assign to the subnet') +param routeTableName string = '' + +@description('Optional. Resource group where route table is deployed. ') +param routeTableResourceGroupName string = resourceGroup().name + +@description('Optional. The service endpoints to enable on the subnet') +param serviceEndpoints array = [] + +@description('Optional. The delegations to enable on the subnet') +param delegations array = [] + +@description('Optional. The name of the NAT Gateway to use for the subnet') +param natGatewayName string = '' + +@description('Optional. enable or disable apply network policies on private end point in the subnet.') +@allowed([ + 'Disabled' + 'Enabled' + '' +]) +param privateEndpointNetworkPolicies string = '' + +@description('Optional. enable or disable apply network policies on private link service in the subnet.') +@allowed([ + 'Disabled' + 'Enabled' + '' +]) +param privateLinkServiceNetworkPolicies string = '' + +@description('Optional. List of address prefixes for the subnet.') +param addressPrefixes array = [] + +@description('Optional. Application gateway IP configurations of virtual network resource.') +param applicationGatewayIpConfigurations array = [] + +@description('Optional. Array of IpAllocation which reference this subnet') +param ipAllocations array = [] + +@description('Optional. An array of service endpoint policies.') +param serviceEndpointPolicies array = [] + +var formattedServiceEndpoints = [for serviceEndpoint in serviceEndpoints: { + service: serviceEndpoint +}] + +@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 virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: virtualNetworkName +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = if (!empty(networkSecurityGroupName)) { + name: networkSecurityGroupName + scope: resourceGroup(networkSecurityGroupNameResourceGroupName) +} + +resource routeTable 'Microsoft.Network/routeTables@2021-05-01' existing = if (!empty(routeTableName)) { + name: routeTableName + scope: resourceGroup(routeTableResourceGroupName) +} + +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' existing = if (!empty(natGatewayName)) { + name: natGatewayName +} + +resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-05-01' = { + name: name + parent: virtualNetwork + properties: { + addressPrefix: addressPrefix + networkSecurityGroup: !empty(networkSecurityGroupName) ? { + id: networkSecurityGroup.id + } : null + routeTable: !empty(routeTableName) ? { + id: routeTable.id + } : null + natGateway: !empty(natGatewayName) ? { + id: natGateway.id + } : null + serviceEndpoints: !empty(formattedServiceEndpoints) ? formattedServiceEndpoints : [] + delegations: delegations + privateEndpointNetworkPolicies: !empty(privateEndpointNetworkPolicies) ? any(privateEndpointNetworkPolicies) : null + privateLinkServiceNetworkPolicies: !empty(privateLinkServiceNetworkPolicies) ? any(privateLinkServiceNetworkPolicies) : null + addressPrefixes: addressPrefixes + applicationGatewayIpConfigurations: applicationGatewayIpConfigurations + ipAllocations: ipAllocations + serviceEndpointPolicies: serviceEndpointPolicies + } +} + +@description('The resource group the virtual network peering was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network peering') +output name string = subnet.name + +@description('The resource ID of the virtual network peering') +output resourceId string = subnet.id + +@description('The address prefix for the subnet') +output subnetAddressPrefix string = subnet.properties.addressPrefix + +@description('List of address prefixes for the subnet') +output subnetAddressPrefixes array = !empty(addressPrefixes) ? subnet.properties.addressPrefixes : [] diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/readme.md b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/readme.md new file mode 100644 index 000000000..7e783a3e6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/readme.md @@ -0,0 +1,73 @@ +# Virtual Network Subnets `[Microsoft.Network/virtualNetworks/subnets]` + +This module deploys a virtual network subnet. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualNetworks/subnets` | 2021-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefix` | string | | | Required. The address prefix for the subnet. | +| `addressPrefixes` | array | `[]` | | Optional. List of address prefixes for the subnet. | +| `applicationGatewayIpConfigurations` | array | `[]` | | Optional. Application gateway IP configurations of virtual network resource. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `delegations` | array | `[]` | | Optional. The delegations to enable on the subnet | +| `ipAllocations` | array | `[]` | | Optional. Array of IpAllocation which reference this subnet | +| `name` | string | | | Optional. The Name of the subnet resource. | +| `natGatewayName` | string | | | Optional. The name of the NAT Gateway to use for the subnet | +| `networkSecurityGroupName` | string | | | Optional. The network security group to assign to the subnet | +| `networkSecurityGroupNameResourceGroupName` | string | `[resourceGroup().name]` | | Optional. Resource Group where NSGs are deployed, if different than VNET Resource Group. | +| `privateEndpointNetworkPolicies` | string | | `[Disabled, Enabled, ]` | Optional. enable or disable apply network policies on private end point in the subnet. | +| `privateLinkServiceNetworkPolicies` | string | | `[Disabled, Enabled, ]` | Optional. enable or disable apply network policies on private link service in the subnet. | +| `routeTableName` | string | | | Optional. The route table to assign to the subnet | +| `serviceEndpointPolicies` | array | `[]` | | Optional. An array of service endpoint policies. | +| `serviceEndpoints` | array | `[]` | | Optional. The service endpoints to enable on the subnet | +| `virtualNetworkName` | string | | | Required. The name of the parent virtual network | + +### Parameter Usage: `delegations` + +```json +"delegations": [ + { + "name": "sqlMiDel", + "properties": { + "serviceName": "Microsoft.Sql/managedInstances" + } + } +] +``` + +### Parameter Usage: `serviceEndpoints` + +```json +"serviceEndpoints": [ + "Microsoft.EventHub", + "Microsoft.Sql", + "Microsoft.Storage", + "Microsoft.KeyVault" +] +``` + +## Considerations + +The `privateEndpointNetworkPolicies` property must be set to disabled for subnets that contain private endpoints. It confirms that NSGs rules will not apply to private endpoints (currently not supported, [reference](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-overview#limitations)). Default Value when not specified is "Enabled". + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network peering | +| `resourceGroupName` | string | The resource group the virtual network peering was deployed into | +| `resourceId` | string | The resource ID of the virtual network peering | +| `subnetAddressPrefix` | string | The address prefix for the subnet | +| `subnetAddressPrefixes` | array | List of address prefixes for the subnet | + +## Template references + +- [Virtualnetworks/Subnets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/subnets) diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/version.json b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/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/carml/1.0.0/Microsoft.Network/virtualNetworks/version.json b/carml/1.0.0/Microsoft.Network/virtualNetworks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/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/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep new file mode 100644 index 000000000..7d482b78f --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep @@ -0,0 +1,59 @@ +@description('Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName') +param name string = '${localVnetName}-${last(split(remoteVirtualNetworkId, '/'))}' + +@description('Required. The Name of the Virtual Network to add the peering to.') +param localVnetName string + +@description('Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID') +param remoteVirtualNetworkId string + +@description('Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true') +param allowForwardedTraffic bool = true + +@description('Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false') +param allowGatewayTransit bool = false + +@description('Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true') +param allowVirtualNetworkAccess bool = true + +@description('Optional. If we need to verify the provisioning state of the remote gateway. Default is true') +param doNotVerifyRemoteGateways bool = true + +@description('Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false') +param useRemoteGateways bool = false + +@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 virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: localVnetName +} + +resource virtualNetworkPeering 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-05-01' = { + name: name + parent: virtualNetwork + properties: { + allowForwardedTraffic: allowForwardedTraffic + allowGatewayTransit: allowGatewayTransit + allowVirtualNetworkAccess: allowVirtualNetworkAccess + doNotVerifyRemoteGateways: doNotVerifyRemoteGateways + useRemoteGateways: useRemoteGateways + remoteVirtualNetwork: { + id: remoteVirtualNetworkId + } + } +} + +@description('The resource group the virtual network peering was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network peering') +output name string = virtualNetworkPeering.name + +@description('The resource ID of the virtual network peering') +output resourceId string = virtualNetworkPeering.id diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md new file mode 100644 index 000000000..7f6731486 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md @@ -0,0 +1,42 @@ +# VirtualNetworkPeering `[Microsoft.Network/virtualNetworks/virtualNetworkPeerings]` + +This template deploys Virtual Network Peering. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | 2021-05-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- Local Virtual Network (Identified by the `localVnetName` parameter). +- Remote Virtual Network (Identified by the `remoteVirtualNetworkId` parameter) + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowForwardedTraffic` | bool | `True` | | Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true | +| `allowGatewayTransit` | bool | `False` | | Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false | +| `allowVirtualNetworkAccess` | bool | `True` | | Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `doNotVerifyRemoteGateways` | bool | `True` | | Optional. If we need to verify the provisioning state of the remote gateway. Default is true | +| `localVnetName` | string | | | Required. The Name of the Virtual Network to add the peering to. | +| `name` | string | `[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]` | | Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName | +| `remoteVirtualNetworkId` | string | | | Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID | +| `useRemoteGateways` | bool | `False` | | Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network peering | +| `resourceGroupName` | string | The resource group the virtual network peering was deployed into | +| `resourceId` | string | The resource ID of the virtual network peering | + +## Template references + +- [Virtualnetworks/Virtualnetworkpeerings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/virtualNetworkPeerings) diff --git a/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/version.json b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/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/carml/1.0.0/Microsoft.Network/virtualWans/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Network/virtualWans/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualWans/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5fa4ad424 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource virtualWan 'Microsoft.Network/virtualWans@2021-03-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualWan.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: virtualWan +}] diff --git a/carml/1.0.0/Microsoft.Network/virtualWans/.parameters/parameters.json b/carml/1.0.0/Microsoft.Network/virtualWans/.parameters/parameters.json new file mode 100644 index 000000000..56ac0a55b --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualWans/.parameters/parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vw-x-001" + }, + "vpnsiteAddressspaceList": { + "value": [] + }, + "vpnsitePublicIPAddress": { + "value": "1.2.3.4" + }, + "vpnsiteBgpAsn": { + "value": 65010 + }, + "vpnsiteBgpPeeringAddress": { + "value": "1.1.1.1" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Network/virtualWans/deploy.bicep b/carml/1.0.0/Microsoft.Network/virtualWans/deploy.bicep new file mode 100644 index 000000000..968b41020 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualWans/deploy.bicep @@ -0,0 +1,189 @@ +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Required. Name of the Virtual Wan.') +param name string + +@description('Optional. Sku of the Virtual Wan.') +@allowed([ + 'Standard' + 'Basic' +]) +param virtualWanSku string = 'Standard' + +@description('Optional. Name of the Virtual Hub. A virtual hub is created inside a virtual wan.') +param virtualHubName string = 'SampleVirtualHub' + +@description('Optional. Name of the Vpn Gateway. A vpn gateway is created inside a virtual hub.') +param vpnGatewayName string = 'SampleVpnGateway' + +@description('Optional. Name of the vpnsite. A vpnsite represents the on-premise vpn device. A public ip address is mandatory for a vpn site creation.') +param vpnSiteName string = 'SampleVpnSite' + +@description('Optional. Name of the vpnconnection. A vpn connection is established between a vpnsite and a vpn gateway.') +param connectionName string = 'SampleVpnsiteVpnGwConnection' + +@description('Optional. A list of static routes corresponding to the vpn site. These are configured on the vpn gateway.') +param vpnsiteAddressspaceList array = [] + +@description('Required. he public IP address of a vpn site.') +param vpnsitePublicIPAddress string + +@description('Required. The bgp asn number of a vpnsite.') +param vpnsiteBgpAsn int + +@description('Required. The bgp peer IP address of a vpnsite.') +param vpnsiteBgpPeeringAddress string + +@description('Optional. The hub address prefix. This address prefix will be used as the address prefix for the hub vnet') +param addressPrefix string = '192.168.0.0/24' + +@description('Optional. his needs to be set to true if BGP needs to enabled on the vpn connection.') +@allowed([ + 'true' + 'false' +]) +param enableBgp string = 'false' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource virtualWan 'Microsoft.Network/virtualWans@2021-03-01' = { + name: name + location: location + tags: tags + properties: { + type: virtualWanSku + } +} + +resource virtualWan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualWan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualWan +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-03-01' = { + name: virtualHubName + location: location + properties: { + addressPrefix: addressPrefix + virtualWan: { + id: virtualWan.id + } + } +} + +resource virtualHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualHub.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualHub +} + +resource vpnSite 'Microsoft.Network/vpnSites@2021-03-01' = { + name: vpnSiteName + location: location + properties: { + addressSpace: { + addressPrefixes: vpnsiteAddressspaceList + } + bgpProperties: { + asn: vpnsiteBgpAsn + bgpPeeringAddress: vpnsiteBgpPeeringAddress + peerWeight: 0 + } + deviceProperties: { + linkSpeedInMbps: 0 + } + ipAddress: vpnsitePublicIPAddress + virtualWan: { + id: virtualWan.id + } + } +} + +resource vpnSite_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vpnSite.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vpnSite +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-03-01' = { + name: vpnGatewayName + location: location + properties: { + connections: [ + { + name: connectionName + properties: { + connectionBandwidth: 10 + enableBgp: any(enableBgp) + remoteVpnSite: { + id: vpnSite.id + } + } + } + ] + virtualHub: { + id: virtualHub.id + } + bgpSettings: { + asn: 65515 + } + } +} + +resource vpnGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vpnGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vpnGateway +} + +module virtualWan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VWan-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualWan.id + } +}] + +@description('The name of the virtual WAN') +output name string = virtualWan.name + +@description('The resource ID of the virtual WAN') +output resourceId string = virtualWan.id + +@description('The resource group the virtual WAN was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Network/virtualWans/readme.md b/carml/1.0.0/Microsoft.Network/virtualWans/readme.md new file mode 100644 index 000000000..24278f39c --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualWans/readme.md @@ -0,0 +1,92 @@ +# Virtual WANs `[Microsoft.Network/virtualWans]` + +This template deploys a virtual WAN. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/virtualHubs` | 2021-03-01 | +| `Microsoft.Network/virtualWans` | 2021-03-01 | +| `Microsoft.Network/vpnGateways` | 2021-03-01 | +| `Microsoft.Network/vpnSites` | 2021-03-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefix` | string | `192.168.0.0/24` | | Optional. The hub address prefix. This address prefix will be used as the address prefix for the hub vnet | +| `connectionName` | string | `SampleVpnsiteVpnGwConnection` | | Optional. Name of the vpnconnection. A vpn connection is established between a vpnsite and a vpn gateway. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enableBgp` | string | `false` | `[true, false]` | Optional. his needs to be set to true if BGP needs to enabled on the vpn connection. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location where all resources will be created. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Name of the Virtual Wan. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `virtualHubName` | string | `SampleVirtualHub` | | Optional. Name of the Virtual Hub. A virtual hub is created inside a virtual wan. | +| `virtualWanSku` | string | `Standard` | `[Standard, Basic]` | Optional. Sku of the Virtual Wan. | +| `vpnGatewayName` | string | `SampleVpnGateway` | | Optional. Name of the Vpn Gateway. A vpn gateway is created inside a virtual hub. | +| `vpnsiteAddressspaceList` | array | `[]` | | Optional. A list of static routes corresponding to the vpn site. These are configured on the vpn gateway. | +| `vpnsiteBgpAsn` | int | | | Required. The bgp asn number of a vpnsite. | +| `vpnsiteBgpPeeringAddress` | string | | | Required. The bgp peer IP address of a vpnsite. | +| `vpnSiteName` | string | `SampleVpnSite` | | Optional. Name of the vpnsite. A vpnsite represents the on-premise vpn device. A public ip address is mandatory for a vpn site creation. | +| `vpnsitePublicIPAddress` | string | | | Required. he public IP address of a vpn site. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual WAN | +| `resourceGroupName` | string | The resource group the virtual WAN was deployed into | +| `resourceId` | string | The resource ID of the virtual WAN | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/virtualHubs) +- [Virtualwans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/virtualWans) +- [Vpngateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/vpnGateways) +- [Vpnsites](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/vpnSites) diff --git a/carml/1.0.0/Microsoft.Network/virtualWans/version.json b/carml/1.0.0/Microsoft.Network/virtualWans/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Network/virtualWans/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/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..86d7d8049 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Azure Sentinel Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade') + 'Azure Sentinel Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb') + 'Azure Sentinel Responder': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Security Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd') + 'Security Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(logAnalyticsWorkspace.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: logAnalyticsWorkspace +}] diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_solutions.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_solutions.bicep new file mode 100644 index 000000000..341438497 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.bicep/nested_solutions.bicep @@ -0,0 +1,32 @@ +param gallerySolution string +param logAnalyticsWorkspaceName string +param location string +param product string = 'OMSGallery' +param publisher string = 'Microsoft' + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource solution 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { + name: '${gallerySolution}(${logAnalyticsWorkspace.name})' + location: location + properties: { + workspaceResourceId: logAnalyticsWorkspace.id + } + plan: { + name: '${gallerySolution}(${logAnalyticsWorkspace.name})' + product: '${product}/${gallerySolution}' + promotionCode: '' + publisher: publisher + } +} + +@description('The resource ID of the deployed solution') +output resourceId string = solution.id + +@description('The resource group where the solution will be deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed solution') +output name string = solution.name diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.parameters/min.parameters.json new file mode 100644 index 000000000..022048939 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-la-min-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.parameters/parameters.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..2f8d6d9b8 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/.parameters/parameters.json @@ -0,0 +1,168 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-la-x-001" + }, + "publicNetworkAccessForIngestion": { + "value": "Disabled" + }, + "publicNetworkAccessForQuery": { + "value": "Disabled" + }, + "dailyQuotaGb": { + "value": 10 + }, + "storageInsightsConfigs": { + "value": [ + { + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsalaw001", + "tables": [ + "WADWindowsEventLogsTable", + "WADETWEventTable", + "WADServiceFabric*EventTable", + "LinuxsyslogVer2v0" + ] + } + ] + }, + "linkedServices": { + "value": [ + { + "name": "Automation", + "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Automation/automationAccounts/adp-<>-wd-aut-x-001" + } + ] + }, + "savedSearches": { + "value": [ + { + "name": "VMSSQueries", + "displayName": "VMSS Instance Count2", + "category": "VDC Saved Searches", + "query": "Event | where Source == 'ServiceFabricNodeBootstrapAgent' | summarize AggregatedValue = count() by Computer" + } + ] + }, + "dataSources": { + "value": [ + { + "name": "applicationEvent", + "kind": "WindowsEvent", + "eventLogName": "Application", + "eventTypes": [ + { + "eventType": "Error" + }, + { + "eventType": "Warning" + }, + { + "eventType": "Information" + } + ] + }, + { + "name": "windowsPerfCounter1", + "kind": "WindowsPerformanceCounter", + "objectName": "Processor", + "instanceName": "*", + "intervalSeconds": 60, + "counterName": "% Processor Time" + }, + { + "name": "sampleIISLog1", + "kind": "IISLogs", + "state": "OnPremiseEnabled" + }, + { + "name": "sampleSyslog1", + "kind": "LinuxSyslog", + "syslogName": "kern", + "syslogSeverities": [ + { + "severity": "emerg" + }, + { + "severity": "alert" + }, + { + "severity": "crit" + }, + { + "severity": "err" + }, + { + "severity": "warning" + } + ] + }, + { + "name": "sampleSyslogCollection1", + "kind": "LinuxSyslogCollection", + "state": "Enabled" + }, + { + "name": "sampleLinuxPerf1", + "kind": "LinuxPerformanceObject", + "syslogSeverities": [ + { + "counterName": "% Used Inodes" + }, + { + "counterName": "Free Megabytes" + }, + { + "counterName": "% Used Space" + }, + { + "counterName": "Disk Transfers/sec" + }, + { + "counterName": "Disk Reads/sec" + }, + { + "counterName": "Disk Writes/sec" + } + ], + "objectName": "Logical Disk", + "instanceName": "*", + "intervalSeconds": 10 + }, + { + "name": "sampleLinuxPerfCollection1", + "kind": "LinuxPerformanceCollection", + "state": "Enabled" + } + ] + }, + "gallerySolutions": { + "value": [ + { + "name": "AzureAutomation", + "product": "OMSGallery", + "publisher": "Microsoft" + } + ] + }, + "useResourcePermissions": { + "value": true + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/deploy.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/deploy.bicep new file mode 100644 index 000000000..53af52a5d --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/deploy.bicep @@ -0,0 +1,95 @@ +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. Name of the solution') +param name string + +@description('Required. The kind of the DataSource.') +@allowed([ + 'AzureActivityLog' + 'WindowsEvent' + 'WindowsPerformanceCounter' + 'IISLogs' + 'LinuxSyslog' + 'LinuxSyslogCollection' + 'LinuxPerformanceObject' + 'LinuxPerformanceCollection' +]) +param kind string = 'AzureActivityLog' + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +@description('Optional. Resource ID of the resource to be linked.') +param linkedResourceId string = '' + +@description('Optional. Windows event log name to configure when kind is WindowsEvent.') +param eventLogName string = '' + +@description('Optional. Windows event types to configure when kind is WindowsEvent.') +param eventTypes array = [] + +@description('Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') +param objectName string = '' + +@description('Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') +param instanceName string = '*' + +@description('Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') +param intervalSeconds int = 60 + +@description('Optional. List of counters to configure when the kind is LinuxPerformanceObject.') +param performanceCounters array = [] + +@description('Optional. Counter name to configure when kind is WindowsPerformanceCounter.') +param counterName string = '' + +@description('Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection.') +param state string = '' + +@description('Optional. System log to configure when kind is LinuxSyslog.') +param syslogName string = '' + +@description('Optional. Severities to configure when kind is LinuxSyslog.') +param syslogSeverities array = [] + +@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 workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource dataSource 'Microsoft.OperationalInsights/workspaces/dataSources@2020-08-01' = { + name: name + parent: workspace + kind: kind + tags: tags + properties: { + linkedResourceId: !empty(kind) && kind == 'AzureActivityLog' ? linkedResourceId : null + eventLogName: !empty(kind) && kind == 'WindowsEvent' ? eventLogName : null + eventTypes: !empty(kind) && kind == 'WindowsEvent' ? eventTypes : null + objectName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? objectName : null + instanceName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? instanceName : null + intervalSeconds: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? intervalSeconds : null + counterName: !empty(kind) && kind == 'WindowsPerformanceCounter' ? counterName : null + state: !empty(kind) && (kind == 'IISLogs' || kind == 'LinuxSyslogCollection' || kind == 'LinuxPerformanceCollection') ? state : null + syslogName: !empty(kind) && kind == 'LinuxSyslog' ? syslogName : null + syslogSeverities: !empty(kind) && (kind == 'LinuxSyslog' || kind == 'LinuxPerformanceObject') ? syslogSeverities : null + performanceCounters: !empty(kind) && kind == 'LinuxPerformanceObject' ? performanceCounters : null + } +} + +@description('The resource ID of the deployed data source') +output resourceId string = dataSource.id + +@description('The resource group where the data source is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed data source') +output name string = dataSource.name diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/readme.md b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/readme.md new file mode 100644 index 000000000..a78f48fe2 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/readme.md @@ -0,0 +1,59 @@ +# Operationalinsights Workspaces Datasources `[Microsoft.OperationalInsights/workspaces/dataSources]` + +This template deploys a data source for a Log Analytics workspace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/dataSources` | 2020-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `counterName` | string | | | Optional. Counter name to configure when kind is WindowsPerformanceCounter. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `eventLogName` | string | | | Optional. Windows event log name to configure when kind is WindowsEvent. | +| `eventTypes` | array | `[]` | | Optional. Windows event types to configure when kind is WindowsEvent. | +| `instanceName` | string | `*` | | Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| `intervalSeconds` | int | `60` | | Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| `kind` | string | `AzureActivityLog` | `[AzureActivityLog, WindowsEvent, WindowsPerformanceCounter, IISLogs, LinuxSyslog, LinuxSyslogCollection, LinuxPerformanceObject, LinuxPerformanceCollection]` | Required. The kind of the DataSource. | +| `linkedResourceId` | string | | | Optional. Resource ID of the resource to be linked. | +| `logAnalyticsWorkspaceName` | string | | | Required. Name of the Log Analytics workspace | +| `name` | string | | | Required. Name of the solution | +| `objectName` | string | | | Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| `performanceCounters` | array | `[]` | | Optional. List of counters to configure when the kind is LinuxPerformanceObject. | +| `state` | string | | | Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection. | +| `syslogName` | string | | | Optional. System log to configure when kind is LinuxSyslog. | +| `syslogSeverities` | array | `[]` | | Optional. Severities to configure when kind is LinuxSyslog. | +| `tags` | object | `{object}` | | Optional. Tags to configure in the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed data source | +| `resourceGroupName` | string | The resource group where the data source is deployed | +| `resourceId` | string | The resource ID of the deployed data source | + +## Template references + +- [Workspaces/Datasources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/dataSources) diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/version.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/dataSources/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/carml/1.0.0/Microsoft.OperationalInsights/workspaces/deploy.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/deploy.bicep new file mode 100644 index 000000000..baed42457 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/deploy.bicep @@ -0,0 +1,261 @@ +@description('Required. Name of the Log Analytics workspace') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Service Tier: PerGB2018, Free, Standalone, PerGB or PerNode') +@allowed([ + 'Free' + 'Standalone' + 'PerNode' + 'PerGB2018' +]) +param serviceTier string = 'PerGB2018' + +@description('Optional. List of storage accounts to be read by the workspace.') +param storageInsightsConfigs array = [] + +@description('Optional. List of services to be linked.') +param linkedServices array = [] + +@description('Optional. Kusto Query Language searches to save.') +param savedSearches array = [] + +@description('Optional. LAW data sources to configure.') +param dataSources array = [] + +@description('Optional. LAW gallerySolutions from the gallery.') +param gallerySolutions array = [] + +@description('Optional. Number of days data will be retained for') +@minValue(0) +@maxValue(730) +param dataRetention int = 365 + +@description('Optional. The workspace daily quota for ingestion.') +@minValue(-1) +param dailyQuotaGb int = -1 + +@description('Optional. The network access type for accessing Log Analytics ingestion.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Optional. The network access type for accessing Log Analytics query.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Optional. Set to \'true\' to use resource or workspace permissions and \'false\' (or leave empty) to require workspace permissions.') +param useResourcePermissions bool = false + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Audit' +]) +param logsToEnable array = [ + 'Audit' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var logAnalyticsSearchVersion = 1 + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' = { + location: location + name: name + tags: tags + properties: { + features: { + searchVersion: logAnalyticsSearchVersion + enableLogAccessUsingOnlyResourcePermissions: useResourcePermissions + } + sku: { + name: serviceTier + } + retentionInDays: dataRetention + workspaceCapping: { + dailyQuotaGb: dailyQuotaGb + } + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + } +} + +resource logAnalyticsWorkspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${logAnalyticsWorkspace.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: logAnalyticsWorkspace +} + +module logAnalyticsWorkspace_storageInsightConfigs 'storageInsightConfigs/deploy.bicep' = [for (storageInsightsConfig, index) in storageInsightsConfigs: { + name: '${uniqueString(deployment().name, location)}-LAW-StorageInsightsConfig-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + containers: contains(storageInsightsConfig, 'containers') ? storageInsightsConfig.containers : [] + tables: contains(storageInsightsConfig, 'tables') ? storageInsightsConfig.tables : [] + storageAccountId: storageInsightsConfig.storageAccountId + } +}] + +module logAnalyticsWorkspace_linkedServices 'linkedServices/deploy.bicep' = [for (linkedService, index) in linkedServices: { + name: '${uniqueString(deployment().name, location)}-LAW-LinkedService-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: linkedService.name + resourceId: linkedService.resourceId + writeAccessResourceId: contains(linkedService, 'writeAccessResourceId') ? linkedService.writeAccessResourceId : '' + } +}] + +module logAnalyticsWorkspace_savedSearches 'savedSearches/deploy.bicep' = [for (savedSearch, index) in savedSearches: { + name: '${uniqueString(deployment().name, location)}-LAW-SavedSearch-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: '${savedSearch.name}${uniqueString(deployment().name)}' + displayName: savedSearch.displayName + category: savedSearch.category + query: savedSearch.query + functionAlias: contains(savedSearch, 'functionAlias') ? savedSearch.functionAlias : '' + functionParameters: contains(savedSearch, 'functionParameters') ? savedSearch.functionParameters : '' + version: contains(savedSearch, 'version') ? savedSearch.version : 2 + } +}] + +module logAnalyticsWorkspace_dataSources 'dataSources/deploy.bicep' = [for (dataSource, index) in dataSources: { + name: '${uniqueString(deployment().name, location)}-LAW-DataSource-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: dataSource.name + kind: dataSource.kind + linkedResourceId: contains(dataSource, 'linkedResourceId') ? dataSource.linkedResourceId : '' + eventLogName: contains(dataSource, 'eventLogName') ? dataSource.eventLogName : '' + eventTypes: contains(dataSource, 'eventTypes') ? dataSource.eventTypes : [] + objectName: contains(dataSource, 'objectName') ? dataSource.objectName : '' + instanceName: contains(dataSource, 'instanceName') ? dataSource.instanceName : '' + intervalSeconds: contains(dataSource, 'intervalSeconds') ? dataSource.intervalSeconds : 60 + counterName: contains(dataSource, 'counterName') ? dataSource.counterName : '' + state: contains(dataSource, 'state') ? dataSource.state : '' + syslogName: contains(dataSource, 'syslogName') ? dataSource.syslogName : '' + syslogSeverities: contains(dataSource, 'syslogSeverities') ? dataSource.syslogSeverities : [] + performanceCounters: contains(dataSource, 'performanceCounters') ? dataSource.performanceCounters : [] + } +}] + +@batchSize(1) // Serial loop deployment +module logAnalyticsWorkspace_solutions '.bicep/nested_solutions.bicep' = [for (gallerySolution, index) in gallerySolutions: if (!empty(gallerySolutions)) { + name: '${uniqueString(deployment().name, location)}-LAW-Solution-${index}' + params: { + gallerySolution: gallerySolution.name + location: location + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + product: gallerySolution.product + publisher: gallerySolution.publisher + } +}] + +resource logAnalyticsWorkspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${logAnalyticsWorkspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: logAnalyticsWorkspace +} + +module logAnalyticsWorkspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LAW-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: logAnalyticsWorkspace.id + } +}] + +@description('The resource ID of the deployed log analytics workspace') +output resourceId string = logAnalyticsWorkspace.id + +@description('The resource group of the deployed log analytics workspace') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed log analytics workspace') +output name string = logAnalyticsWorkspace.name + +@description('The ID associated with the workspace') +output logAnalyticsWorkspaceId string = logAnalyticsWorkspace.properties.customerId diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/deploy.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/deploy.bicep new file mode 100644 index 000000000..b54dab3c7 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/deploy.bicep @@ -0,0 +1,45 @@ +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. Name of the link') +param name string + +@description('Required. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access.') +param resourceId string = '' + +@description('Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access. ') +param writeAccessResourceId string = '' + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +@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 workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource linkedService 'Microsoft.OperationalInsights/workspaces/linkedServices@2020-08-01' = { + name: name + parent: workspace + tags: tags + properties: { + resourceId: resourceId + writeAccessResourceId: empty(writeAccessResourceId) ? null : writeAccessResourceId + } +} + +@description('The resource ID of the deployed linked service') +output resourceId string = linkedService.id + +@description('The resource group where the linked service is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed linked service') +output name string = linkedService.name diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/readme.md b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/readme.md new file mode 100644 index 000000000..4f6fa0583 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/readme.md @@ -0,0 +1,49 @@ +# Operationalinsights Workspaces Linked Services `[Microsoft.OperationalInsights/workspaces/linkedServices]` + +This template deploys a linked service for a Log Analytics workspace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | 2020-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `logAnalyticsWorkspaceName` | string | | | Required. Name of the Log Analytics workspace | +| `name` | string | | | Required. Name of the link | +| `resourceId` | string | | | Required. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access. | +| `tags` | object | `{object}` | | Optional. Tags to configure in the resource. | +| `writeAccessResourceId` | string | | | Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed linked service | +| `resourceGroupName` | string | The resource group where the linked service is deployed | +| `resourceId` | string | The resource ID of the deployed linked service | + +## Template references + +- [Workspaces/Linkedservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedServices) diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/version.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/linkedServices/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/carml/1.0.0/Microsoft.OperationalInsights/workspaces/readme.md b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/readme.md new file mode 100644 index 000000000..0856da74c --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/readme.md @@ -0,0 +1,140 @@ +# Log Analytics Workspaces `[Microsoft.OperationalInsights/workspaces]` + +This template deploys a log analytics workspace. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.OperationalInsights/workspaces` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/dataSources` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/savedSearches` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/storageInsightConfigs` | 2020-08-01 | +| `Microsoft.OperationsManagement/solutions` | 2015-11-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 | +| `dailyQuotaGb` | int | `-1` | | Optional. The workspace daily quota for ingestion. | +| `dataRetention` | int | `365` | | Optional. Number of days data will be retained for | +| `dataSources` | _[dataSources](dataSources/readme.md)_ array | `[]` | | Optional. LAW data sources to configure. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of a log analytics workspace. | +| `gallerySolutions` | array | `[]` | | Optional. LAW gallerySolutions from the gallery. | +| `linkedServices` | _[linkedServices](linkedServices/readme.md)_ array | `[]` | | Optional. List of services to be linked. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[Audit]` | `[Audit]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the Log Analytics workspace | +| `publicNetworkAccessForIngestion` | string | `Enabled` | `[Enabled, Disabled]` | Optional. The network access type for accessing Log Analytics ingestion. | +| `publicNetworkAccessForQuery` | string | `Enabled` | `[Enabled, Disabled]` | Optional. The network access type for accessing Log Analytics query. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `savedSearches` | _[savedSearches](savedSearches/readme.md)_ array | `[]` | | Optional. Kusto Query Language searches to save. | +| `serviceTier` | string | `PerGB2018` | `[Free, Standalone, PerNode, PerGB2018]` | Optional. Service Tier: PerGB2018, Free, Standalone, PerGB or PerNode | +| `storageInsightsConfigs` | array | `[]` | | Optional. List of storage accounts to be read by the workspace. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `useResourcePermissions` | bool | | | Optional. Set to 'true' to use resource or workspace permissions and 'false' (or leave empty) to require workspace permissions. | + +### Parameter Usage: `gallerySolutions` + +```json +"gallerySolutions": { + "value": [ + "AgentHealthAssessment", + "AlertManagement", + "AntiMalware", + "AzureActivity", + //"AzureAppGatewayAnalytics", + "AzureAutomation", + "AzureCdnCoreAnalytics", + "AzureDataFactoryAnalytics", + "AzureNSGAnalytics", + "AzureSQLAnalytics", + "ChangeTracking", + "Containers", + "InfrastructureInsights", + "KeyVaultAnalytics", + "LogicAppsManagement", + "NetworkMonitoring", + "Security", + "SecurityCenterFree", + "ServiceFabric", + "ServiceMap", + "SQLAssessment", + "Updates", + "VMInsights", + "WireData2", + "WaaSUpdateInsights" + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `logAnalyticsWorkspaceId` | string | The ID associated with the workspace | +| `name` | string | The name of the deployed log analytics workspace | +| `resourceGroupName` | string | The resource group of the deployed log analytics workspace | +| `resourceId` | string | The resource ID of the deployed log analytics workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Solutions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces) +- [Workspaces/Datasources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/dataSources) +- [Workspaces/Linkedservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedServices) +- [Workspaces/Savedsearches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/savedSearches) +- [Workspaces/Storageinsightconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/storageInsightConfigs) diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/deploy.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/deploy.bicep new file mode 100644 index 000000000..cf3e1f915 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/deploy.bicep @@ -0,0 +1,61 @@ +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. Name of the saved search') +param name string + +@description('Required. Display name for the search.') +param displayName string + +@description('Required. Query category.') +param category string + +@description('Required. Kusto Query to be stored.') +param query string + +@description('Optional. Tags to configure in the resource.') +param tags array = [] + +@description('Optional. The function alias if query serves as a function..') +param functionAlias string = '' + +@description('Optional. The optional function parameters if query serves as a function. Value should be in the following format: "param-name1:type1 = default_value1, param-name2:type2 = default_value2". For more examples and proper syntax please refer to /azure/kusto/query/functions/user-defined-functions.') +param functionParameters string = '' + +@description('Optional. The version number of the query language.') +param version int = 2 + +@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 workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource savedSearch 'Microsoft.OperationalInsights/workspaces/savedSearches@2020-08-01' = { + name: name + parent: workspace + properties: { + tags: tags + displayName: displayName + category: category + query: query + functionAlias: functionAlias + functionParameters: functionParameters + version: version + } +} + +@description('The resource ID of the deployed saved search') +output resourceId string = savedSearch.id + +@description('The resource group where the saved search is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed saved search') +output name string = savedSearch.name diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/readme.md b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/readme.md new file mode 100644 index 000000000..f3769ba87 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/readme.md @@ -0,0 +1,53 @@ +# Operationalinsights Workspaces Saved Searches `[Microsoft.OperationalInsights/workspaces/savedSearches]` + +This template deploys a saved search for a Log Analytics workspace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/savedSearches` | 2020-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `category` | string | | | Required. Query category. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `displayName` | string | | | Required. Display name for the search. | +| `functionAlias` | string | | | Optional. The function alias if query serves as a function.. | +| `functionParameters` | string | | | Optional. The optional function parameters if query serves as a function. Value should be in the following format: "param-name1:type1 = default_value1, param-name2:type2 = default_value2". For more examples and proper syntax please refer to /azure/kusto/query/functions/user-defined-functions. | +| `logAnalyticsWorkspaceName` | string | | | Required. Name of the Log Analytics workspace | +| `name` | string | | | Required. Name of the saved search | +| `query` | string | | | Required. Kusto Query to be stored. | +| `tags` | array | `[]` | | Optional. Tags to configure in the resource. | +| `version` | int | `2` | | Optional. The version number of the query language. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed saved search | +| `resourceGroupName` | string | The resource group where the saved search is deployed | +| `resourceId` | string | The resource ID of the deployed saved search | + +## Template references + +- [Workspaces/Savedsearches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/savedSearches) diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/version.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/savedSearches/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/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/deploy.bicep b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/deploy.bicep new file mode 100644 index 000000000..6890c6e3f --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. Name of the Log Analytics workspace.') +param logAnalyticsWorkspaceName string + +@description('Optional. The name of the storage insights config') +param name string = '${last(split(storageAccountId, '/'))}-stinsconfig' + +@description('Required. The Azure Resource Manager ID of the storage account resource.') +param storageAccountId string + +@description('Optional. The names of the blob containers that the workspace should read.') +param containers array = [] + +@description('Optional. The names of the Azure tables that the workspace should read.') +param tables array = [] + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: last(split(storageAccountId, '/')) +} + +resource workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource storageinsightconfig 'Microsoft.OperationalInsights/workspaces/storageInsightConfigs@2020-08-01' = { + name: name + parent: workspace + tags: tags + properties: { + containers: containers + tables: tables + storageAccount: { + id: storageAccountId + key: storageAccount.listKeys().keys[0].value + } + } +} + +@description('The resource ID of the deployed storage insights configuration') +output resourceId string = storageinsightconfig.id + +@description('The resource group where the storage insight configuration is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the storage insights configuration') +output name string = storageinsightconfig.name diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/readme.md b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/readme.md new file mode 100644 index 000000000..d8d521b10 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/readme.md @@ -0,0 +1,50 @@ +# Operationalinsights Workspaces Storage Insight Configs `[Microsoft.OperationalInsights/workspaces/storageInsightConfigs]` + +This template deploys a storage insights configuration for a Log Analytics workspace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/storageInsightConfigs` | 2020-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `containers` | array | `[]` | | Optional. The names of the blob containers that the workspace should read. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `logAnalyticsWorkspaceName` | string | | | Required. Name of the Log Analytics workspace. | +| `name` | string | `[format('{0}-stinsconfig', last(split(parameters('storageAccountId'), '/')))]` | | Optional. The name of the storage insights config | +| `storageAccountId` | string | | | Required. The Azure Resource Manager ID of the storage account resource. | +| `tables` | array | `[]` | | Optional. The names of the Azure tables that the workspace should read. | +| `tags` | object | `{object}` | | Optional. Tags to configure in the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the storage insights configuration | +| `resourceGroupName` | string | The resource group where the storage insight configuration is deployed | +| `resourceId` | string | The resource ID of the deployed storage insights configuration | + +## Template references + +- [Workspaces/Storageinsightconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/storageInsightConfigs) diff --git a/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/version.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/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/carml/1.0.0/Microsoft.OperationalInsights/workspaces/version.json b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.OperationalInsights/workspaces/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/carml/1.0.0/Microsoft.RecoveryServices/vaults/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4b3dcbe5d --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.bicep/nested_rbac.bicep @@ -0,0 +1,39 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(rsv.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: rsv +}] diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.parameters/min.parameters.json new file mode 100644 index 000000000..81ba350a3 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rsv-min-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/.parameters/parameters.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.parameters/parameters.json new file mode 100644 index 000000000..dead4aa14 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/.parameters/parameters.json @@ -0,0 +1,286 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rsv-x-001" + }, + "backupConfig": { + "value": { + "enhancedSecurityState": "Disabled", + "softDeleteFeatureState": "Disabled" + } + }, + "backupPolicies": { + "value": [ + { + "name": "VMpolicy", + "properties": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 180, + "durationType": "Days" + } + }, + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + }, + "instantRpRetentionRangeInDays": 2, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + }, + { + "name": "sqlpolicy", + "properties": { + "backupManagementType": "AzureWorkload", + "workLoadType": "SQLDataBase", + "settings": { + "timeZone": "UTC", + "issqlcompression": true, + "isCompression": true + }, + "subProtectionPolicy": [ + { + "policyType": "Full", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Sunday" + ], + "scheduleRunTimes": [ + "2019-11-07T22:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 104, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + } + }, + { + "policyType": "Differential", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Monday" + ], + "scheduleRunTimes": [ + "2017-03-07T02:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + { + "policyType": "Log", + "schedulePolicy": { + "schedulePolicyType": "LogSchedulePolicy", + "scheduleFrequencyInMins": 120 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 15, + "durationType": "Days" + } + } + } + ], + "protectedItemsCount": 0 + } + }, + { + "name": "filesharepolicy", + "properties": { + "backupManagementType": "AzureStorage", + "workloadType": "AzureFileShare", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T04:30:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T04:30:00Z" + ], + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + } + ] + }, + "backupStorageConfig": { + "value": { + "storageModelType": "GeoRedundant", + "crossRegionRestoreFlag": true + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/deploy.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/deploy.bicep new file mode 100644 index 000000000..2553c6443 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/deploy.bicep @@ -0,0 +1,81 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Optional. Name of the Azure Recovery Service Vault Backup Policy') +param name string = 'vaultconfig' + +@description('Optional. Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param enhancedSecurityState string = 'Enabled' + +@description('Optional. ResourceGuard Operation Requests') +param resourceGuardOperationRequests array = [] + +@description('Optional. Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes') +@allowed([ + 'Disabled' + 'Enabled' +]) +param softDeleteFeatureState string = 'Enabled' + +@description('Optional. Storage type') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageModelType string = 'GeoRedundant' + +@description('Optional. Storage type') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageType string = 'GeoRedundant' + +@description('Optional. Once a machine is registered against a resource, the storageTypeState is always Locked.') +@allowed([ + 'Locked' + 'Unlocked' +]) +param storageTypeState string = 'Locked' + +@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 rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: recoveryVaultName +} + +resource backupConfig 'Microsoft.RecoveryServices/vaults/backupconfig@2021-10-01' = { + name: name + parent: rsv + properties: { + enhancedSecurityState: enhancedSecurityState + resourceGuardOperationRequests: resourceGuardOperationRequests + softDeleteFeatureState: softDeleteFeatureState + storageModelType: storageModelType + storageType: storageType + storageTypeState: storageTypeState + } +} + +@description('The name of the backup config') +output name string = backupConfig.name + +@description('The resource ID of the backup config') +output resourceId string = backupConfig.id + +@description('The name of the resource group the backup config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/readme.md b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/readme.md new file mode 100644 index 000000000..778bd4199 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/readme.md @@ -0,0 +1,35 @@ +# Recovery Services Vault Backup Config `[Microsoft.RecoveryServices/vaults/backupconfig]` + +This module deploys recovery services vault backup config. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupconfig` | 2021-10-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `enhancedSecurityState` | string | `Enabled` | `[Disabled, Enabled]` | Optional. Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations. | +| `name` | string | `vaultconfig` | | Optional. Name of the Azure Recovery Service Vault Backup Policy | +| `recoveryVaultName` | string | | | Required. Name of the Azure Recovery Service Vault | +| `resourceGuardOperationRequests` | array | `[]` | | Optional. ResourceGuard Operation Requests | +| `softDeleteFeatureState` | string | `Enabled` | `[Disabled, Enabled]` | Optional. Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes | +| `storageModelType` | string | `GeoRedundant` | `[GeoRedundant, LocallyRedundant, ReadAccessGeoZoneRedundant, ZoneRedundant]` | Optional. Storage type | +| `storageType` | string | `GeoRedundant` | `[GeoRedundant, LocallyRedundant, ReadAccessGeoZoneRedundant, ZoneRedundant]` | Optional. Storage type | +| `storageTypeState` | string | `Locked` | `[Locked, Unlocked]` | Optional. Once a machine is registered against a resource, the storageTypeState is always Locked. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup config | +| `resourceGroupName` | string | The name of the resource group the backup config was created in. | +| `resourceId` | string | The resource ID of the backup config | + +## Template references + +- [Vaults/Backupconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-10-01/vaults/backupconfig) diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/version.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupConfig/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/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/deploy.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/deploy.bicep new file mode 100644 index 000000000..71042ec9f --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/deploy.bicep @@ -0,0 +1,35 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. Name of the Azure Recovery Service Vault Backup Policy') +param name string + +@description('Required. Configuration of the Azure Recovery Service Vault Backup Policy') +param backupPolicyProperties object + +@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 rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: recoveryVaultName +} + +resource backupPolicy 'Microsoft.RecoveryServices/vaults/backupPolicies@2021-08-01' = { + name: name + parent: rsv + properties: backupPolicyProperties +} + +@description('The name of the backup policy') +output name string = backupPolicy.name + +@description('The resource ID of the backup policy') +output resourceId string = backupPolicy.id + +@description('The name of the resource group the backup policy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/readme.md b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/readme.md new file mode 100644 index 000000000..df867a4bc --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/readme.md @@ -0,0 +1,118 @@ +# RecoveryServicesVaultsBackupPolicies `[Microsoft.RecoveryServices/vaults/backupPolicies]` + +This module deploys a Backup Policy for a Recovery Services Vault + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupPolicies` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupPolicyProperties` | object | | | Required. Configuration of the Azure Recovery Service Vault Backup Policy | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Name of the Azure Recovery Service Vault Backup Policy | +| `recoveryVaultName` | string | | | Required. Name of the Azure Recovery Service Vault | + +### Parameter Usage: `backupPolicyProperties` + +Object continaining the configuration for backup policies. It needs to be properly formatted and can be VM backup policies, SQL on VM backup policies or fileshare policies. The following example shows a VM backup policy. + +```json +"backupPolicyProperties": { + "value": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 180, + "durationType": "Days" + } + }, + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + }, + "instantRpRetentionRangeInDays": 2, + "timeZone": "UTC", + "protectedItemsCount": 0 + } +} +``` + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup policy | +| `resourceGroupName` | string | The name of the resource group the backup policy was created in. | +| `resourceId` | string | The resource ID of the backup policy | + +## Template references + +- [Vaults/Backuppolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupPolicies) diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/version.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupPolicies/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/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/deploy.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/deploy.bicep new file mode 100644 index 000000000..c4c89c200 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/deploy.bicep @@ -0,0 +1,47 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Optional. The name of the backup storage config') +param name string = 'vaultstorageconfig' + +@description('Optional. Change Vault Storage Type (Works if vault has not registered any backup instance)') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageModelType string = 'GeoRedundant' + +@description('Optional. Opt in details of Cross Region Restore feature') +param crossRegionRestoreFlag bool = true + +@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 rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: recoveryVaultName +} + +resource backupStorageConfig 'Microsoft.RecoveryServices/vaults/backupstorageconfig@2021-08-01' = { + name: name + parent: rsv + properties: { + storageModelType: storageModelType + crossRegionRestoreFlag: crossRegionRestoreFlag + } +} + +@description('The name of the backup storage config') +output name string = backupStorageConfig.name + +@description('The resource ID of the backup storage config') +output resourceId string = backupStorageConfig.id + +@description('The name of the Resource Group the backup storage configuration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md new file mode 100644 index 000000000..e4502785b --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md @@ -0,0 +1,30 @@ +# RecoveryServicesVaultsBackupStorageConfig `[Microsoft.RecoveryServices/vaults/backupstorageconfig]` + +This module deploys the Backup Storage Configuration for the Recovery Service Vault +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupstorageconfig` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `crossRegionRestoreFlag` | bool | `True` | | Optional. Opt in details of Cross Region Restore feature | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `vaultstorageconfig` | | Optional. The name of the backup storage config | +| `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 | +| :-- | :-- | :-- | +| `name` | string | The name of the backup storage config | +| `resourceGroupName` | string | The name of the Resource Group the backup storage configuration was created in. | +| `resourceId` | string | The resource ID of the backup storage config | + +## Template references + +- [Vaults/Backupstorageconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupstorageconfig) diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/version.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/backupStorageConfig/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/carml/1.0.0/Microsoft.RecoveryServices/vaults/deploy.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/deploy.bicep new file mode 100644 index 000000000..558f71c24 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/deploy.bicep @@ -0,0 +1,230 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param name string + +@description('Optional. The storage configuration for the Azure Recovery Service Vault') +param backupStorageConfig object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. List of all backup policies.') +param backupPolicies array = [] + +@description('Optional. The backup configuration.') +param backupConfig object = {} + +@description('Optional. List of all protection containers.') +@minLength(0) +param protectionContainers array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the Recovery Service Vault resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AzureBackupReport' + 'CoreAzureBackup' + 'AddonAzureBackupJobs' + 'AddonAzureBackupAlerts' + 'AddonAzureBackupPolicy' + 'AddonAzureBackupStorage' + 'AddonAzureBackupProtectedInstance' + 'AzureSiteRecoveryJobs' + 'AzureSiteRecoveryEvents' + 'AzureSiteRecoveryReplicatedItems' + 'AzureSiteRecoveryReplicationStats' + 'AzureSiteRecoveryRecoveryPoints' + 'AzureSiteRecoveryReplicationDataUploadRate' + 'AzureSiteRecoveryProtectedDiskDataChurn' +]) +param logsToEnable array = [ + 'AzureBackupReport' + 'CoreAzureBackup' + 'AddonAzureBackupJobs' + 'AddonAzureBackupAlerts' + 'AddonAzureBackupPolicy' + 'AddonAzureBackupStorage' + 'AddonAzureBackupProtectedInstance' + 'AzureSiteRecoveryJobs' + 'AzureSiteRecoveryEvents' + 'AzureSiteRecoveryReplicatedItems' + 'AzureSiteRecoveryReplicationStats' + 'AzureSiteRecoveryRecoveryPoints' + 'AzureSiteRecoveryReplicationDataUploadRate' + 'AzureSiteRecoveryProtectedDiskDataChurn' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Health' +]) +param metricsToEnable array = [ + 'Health' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' = { + name: name + location: location + tags: tags + identity: any(identity) + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: {} +} + +module rsv_backupStorageConfiguration 'backupStorageConfig/deploy.bicep' = if (!empty(backupStorageConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupStorageConfig' + params: { + recoveryVaultName: rsv.name + storageModelType: backupStorageConfig.storageModelType + crossRegionRestoreFlag: backupStorageConfig.crossRegionRestoreFlag + } +} + +module rsv_protectionContainers 'protectionContainers/deploy.bicep' = [for (protectionContainer, index) in protectionContainers: { + name: '${uniqueString(deployment().name, location)}-RSV-ProtectionContainers-${index}' + params: { + recoveryVaultName: rsv.name + name: protectionContainer.name + sourceResourceId: protectionContainer.sourceResourceId + friendlyName: protectionContainer.friendlyName + backupManagementType: protectionContainer.backupManagementType + containerType: protectionContainer.containerType + } +}] + +module rsv_backupPolicies 'backupPolicies/deploy.bicep' = [for (backupPolicy, index) in backupPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-BackupPolicy-${index}' + params: { + recoveryVaultName: rsv.name + name: backupPolicy.name + backupPolicyProperties: backupPolicy.properties + } +}] + +module rsv_backupConfig 'backupConfig/deploy.bicep' = if (!empty(backupConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupConfig' + params: { + recoveryVaultName: rsv.name + name: contains(backupConfig, 'name') ? backupConfig.name : 'vaultconfig' + enhancedSecurityState: contains(backupConfig, 'enhancedSecurityState') ? backupConfig.enhancedSecurityState : 'Enabled' + resourceGuardOperationRequests: contains(backupConfig, 'resourceGuardOperationRequests') ? backupConfig.resourceGuardOperationRequests : [] + softDeleteFeatureState: contains(backupConfig, 'softDeleteFeatureState') ? backupConfig.softDeleteFeatureState : 'Enabled' + storageModelType: contains(backupConfig, 'storageModelType') ? backupConfig.storageModelType : 'GeoRedundant' + storageType: contains(backupConfig, 'storageType') ? backupConfig.storageType : 'GeoRedundant' + storageTypeState: contains(backupConfig, 'storageTypeState') ? backupConfig.storageTypeState : 'Locked' + } +} + +resource rsv_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${rsv.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: rsv +} + +resource rsv_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${rsv.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: rsv +} + +module rsv_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RSV-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: rsv.id + } +}] + +@description('The resource ID of the recovery services vault') +output resourceId string = rsv.id + +@description('The name of the resource group the recovery services vault was created in') +output resourceGroupName string = resourceGroup().name + +@description('The Name of the recovery services vault') +output name string = rsv.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(rsv.identity, 'principalId') ? rsv.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/deploy.bicep b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/deploy.bicep new file mode 100644 index 000000000..d8dfad71f --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/deploy.bicep @@ -0,0 +1,68 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. Name of the Azure Recovery Service Vault Protection Container') +param name string + +@description('Optional. Backup management type to execute the current Protection Container job.') +@allowed([ + 'AzureBackupServer' + 'AzureIaasVM' + 'AzureSql' + 'AzureStorage' + 'AzureWorkload' + 'DPM' + 'DefaultBackup' + 'Invalid' + 'MAB' + '' +]) +param backupManagementType string = '' + +@description('Optional. Resource ID of the target resource for the Protection Container ') +param sourceResourceId string = '' + +@description('Optional. Friendly name of the Protection Container') +param friendlyName string = '' + +@description('Optional. Type of the container') +@allowed([ + 'AzureBackupServerContainer' + 'AzureSqlContainer' + 'GenericContainer' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'SQLAGWorkLoadContainer' + 'StorageContainer' + 'VMAppContainer' + 'Windows' + '' +]) +param containerType string = '' + +@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 protectionContainer 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers@2021-08-01' = { + name: '${recoveryVaultName}/Azure/${name}' + properties: { + sourceResourceId: !empty(sourceResourceId) ? sourceResourceId : null + friendlyName: !empty(friendlyName) ? friendlyName : null + backupManagementType: !empty(backupManagementType) ? backupManagementType : null + containerType: !empty(containerType) ? any(containerType) : null + } +} + +@description('The name of the Resource Group the Protection Container was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Protection Container.') +output resourceId string = protectionContainer.id + +@description('The Name of the Protection Container.') +output name string = protectionContainer.name diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/readme.md b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/readme.md new file mode 100644 index 000000000..b07c22176 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/readme.md @@ -0,0 +1,33 @@ +# RecoveryServicesProtectionContainer `[Microsoft.RecoveryServices/vaults/protectionContainers]` + +This module deploys a Protection Container for a Recovery Services Vault + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupManagementType` | string | | `[AzureBackupServer, AzureIaasVM, AzureSql, AzureStorage, AzureWorkload, DPM, DefaultBackup, Invalid, MAB, ]` | Optional. Backup management type to execute the current Protection Container job. | +| `containerType` | string | | `[AzureBackupServerContainer, AzureSqlContainer, GenericContainer, Microsoft.ClassicCompute/virtualMachines, Microsoft.Compute/virtualMachines, SQLAGWorkLoadContainer, StorageContainer, VMAppContainer, Windows, ]` | Optional. Type of the container | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `friendlyName` | string | | | Optional. Friendly name of the Protection Container | +| `name` | string | | | Required. Name of the Azure Recovery Service Vault Protection Container | +| `recoveryVaultName` | string | | | Required. Name of the Azure Recovery Service Vault | +| `sourceResourceId` | string | | | Optional. Resource ID of the target resource for the Protection Container | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the Protection Container. | +| `resourceGroupName` | string | The name of the Resource Group the Protection Container was created in. | +| `resourceId` | string | The resource ID of the Protection Container. | + +## Template references + +- [Vaults/Backupfabrics/Protectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupFabrics/protectionContainers) diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/version.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/protectionContainers/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/carml/1.0.0/Microsoft.RecoveryServices/vaults/readme.md b/carml/1.0.0/Microsoft.RecoveryServices/vaults/readme.md new file mode 100644 index 000000000..94bdb7301 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/readme.md @@ -0,0 +1,365 @@ +# Recovery Services Vaults `[Microsoft.RecoveryServices/vaults]` + +This module deploys a recovery service vault. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.RecoveryServices/vaults` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/backupconfig` | 2021-10-01 | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers` | 2021-08-01 | +| `Microsoft.RecoveryServices/vaults/backupPolicies` | 2021-08-01 | +| `Microsoft.RecoveryServices/vaults/backupstorageconfig` | 2021-08-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupConfig` | _[backupConfig](backupConfig/readme.md)_ object | `{object}` | | Optional. The backup configuration. | +| `backupPolicies` | _[backupPolicies](backupPolicies/readme.md)_ array | `[]` | | Optional. List of all backup policies. | +| `backupStorageConfig` | _[backupStorageConfig](backupStorageConfig/readme.md)_ object | `{object}` | | Optional. The storage configuration for the Azure Recovery Service Vault | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[AzureBackupReport, CoreAzureBackup, AddonAzureBackupJobs, AddonAzureBackupAlerts, AddonAzureBackupPolicy, AddonAzureBackupStorage, AddonAzureBackupProtectedInstance, AzureSiteRecoveryJobs, AzureSiteRecoveryEvents, AzureSiteRecoveryReplicatedItems, AzureSiteRecoveryReplicationStats, AzureSiteRecoveryRecoveryPoints, AzureSiteRecoveryReplicationDataUploadRate, AzureSiteRecoveryProtectedDiskDataChurn]` | `[AzureBackupReport, CoreAzureBackup, AddonAzureBackupJobs, AddonAzureBackupAlerts, AddonAzureBackupPolicy, AddonAzureBackupStorage, AddonAzureBackupProtectedInstance, AzureSiteRecoveryJobs, AzureSiteRecoveryEvents, AzureSiteRecoveryReplicatedItems, AzureSiteRecoveryReplicationStats, AzureSiteRecoveryRecoveryPoints, AzureSiteRecoveryReplicationDataUploadRate, AzureSiteRecoveryProtectedDiskDataChurn]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[Health]` | `[Health]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the Azure Recovery Service Vault | +| `protectionContainers` | _[protectionContainers](protectionContainers/readme.md)_ array | `[]` | | Optional. List of all protection containers. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the Recovery Service Vault resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `backupStorageConfig` + +```json +"backupStorageConfig": { + "value": { + "storageModelType": "GeoRedundant", + "crossRegionRestoreFlag": true + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `backupPolicies` + +Array of backup policies. They need to be properly formatted and can be VM backup policies, SQL on VM backup policies or fileshare policies. The following example shows all three types of backup policies. + +```json +"backupPolicies": { + "value": [ + { + "name": "VMpolicy", + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "properties": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 180, + "durationType": "Days" + } + }, + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + }, + "instantRpRetentionRangeInDays": 2, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + }, + { + "name": "sqlpolicy", + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "properties": { + "backupManagementType": "AzureWorkload", + "workLoadType": "SQLDataBase", + "settings": { + "timeZone": "UTC", + "issqlcompression": true, + "isCompression": true + }, + "subProtectionPolicy": [ + { + "policyType": "Full", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Sunday" + ], + "scheduleRunTimes": [ + "2019-11-07T22:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 104, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + } + }, + { + "policyType": "Differential", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Monday" + ], + "scheduleRunTimes": [ + "2017-03-07T02:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + { + "policyType": "Log", + "schedulePolicy": { + "schedulePolicyType": "LogSchedulePolicy", + "scheduleFrequencyInMins": 120 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 15, + "durationType": "Days" + } + } + } + ], + "protectedItemsCount": 0 + } + }, + { + "name": "filesharepolicy", + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "properties": { + "backupManagementType": "AzureStorage", + "workloadType": "AzureFileShare", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T04:30:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T04:30:00Z" + ], + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the recovery services vault | +| `resourceGroupName` | string | The name of the resource group the recovery services vault was created in | +| `resourceId` | string | The resource ID of the recovery services vault | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/vaults) +- [Vaults/Backupconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-10-01/vaults/backupconfig) +- [Vaults/Backupfabrics/Protectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupFabrics/protectionContainers) +- [Vaults/Backuppolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupPolicies) +- [Vaults/Backupstorageconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupstorageconfig) diff --git a/carml/1.0.0/Microsoft.RecoveryServices/vaults/version.json b/carml/1.0.0/Microsoft.RecoveryServices/vaults/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.RecoveryServices/vaults/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/carml/1.0.0/Microsoft.Resources/deploymentScripts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Resources/deploymentScripts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Resources/deploymentScripts/.parameters/cli.parameters.json b/carml/1.0.0/Microsoft.Resources/deploymentScripts/.parameters/cli.parameters.json new file mode 100644 index 000000000..e3e775a93 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/.parameters/cli.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": "<>-az-ds-cli-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "kind": { + "value": "AzureCLI" + }, + "azCliVersion": { + "value": "2.15.0" + }, + "scriptContent": { + "value": "echo \"Hello from inside the script\"" + }, + "retentionInterval": { + "value": "P1D" + }, + "runOnce": { + "value": false + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT30M" + } + } +} diff --git a/carml/1.0.0/Microsoft.Resources/deploymentScripts/.parameters/ps.parameters.json b/carml/1.0.0/Microsoft.Resources/deploymentScripts/.parameters/ps.parameters.json new file mode 100644 index 000000000..9f780f49a --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/.parameters/ps.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": "<>-az-ds-ps-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "kind": { + "value": "AzurePowerShell" + }, + "azPowerShellVersion": { + "value": "3.0" + }, + "scriptContent": { + "value": "Write-Host 'Running PowerShell from template'" + }, + "retentionInterval": { + "value": "P1D" + }, + "runOnce": { + "value": false + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT30M" + } + } +} diff --git a/carml/1.0.0/Microsoft.Resources/deploymentScripts/check-avd-entapp.bicep b/carml/1.0.0/Microsoft.Resources/deploymentScripts/check-avd-entapp.bicep new file mode 100644 index 000000000..b83a4287c --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/check-avd-entapp.bicep @@ -0,0 +1,132 @@ +@description('Required. Display name of the script to be run.') +param name string + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Type of the script. AzurePowerShell, AzureCLI.') +@allowed([ + 'AzurePowerShell' + 'AzureCLI' +]) +param kind string = 'AzurePowerShell' + +@description('Optional. Azure PowerShell module version to be used.') +param azPowerShellVersion string = '3.0' + +@description('Optional. Azure CLI module version to be used.') +param azCliVersion string = '' + +@description('Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead.') +param scriptContent string = '' + +@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead.') +param primaryScriptUri string = '' + +@description('Optional. The environment variables to pass over to the script. Must have a \'name\' and a \'value\' or a \'secretValue\' property.') +param environmentVariables array = [] + +@description('Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent).') +param supportingScriptUris array = [] + +@description('Optional. Command-line arguments to pass to the script. Arguments are separated by spaces.') +param arguments string = '' + +@description('Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week).') +param retentionInterval string = 'P1D' + +@description('Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once.') +param runOnce bool = false + +@description('Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled).') +@allowed([ + 'Always' + 'OnSuccess' + 'OnExpiration' +]) +param cleanupPreference string = 'Always' + +@description('Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a \'containerGroupName\' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use \'containerGroupName\' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. \'containerGroupName\' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed.') +param containerGroupName string = '' + +@description('Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; \'PT30M\' - 30 minutes; \'P5D\' - 5 days; \'P1Y\' 1 year.') +param timeout string = 'PT6H' + +@description('Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var containerSettings = { + containerGroupName: containerGroupName +} + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: name + location: location + tags: tags + identity: identity + kind: any(kind) + properties: { + azPowerShellVersion: kind == 'AzurePowerShell' ? azPowerShellVersion : null + azCliVersion: kind == 'AzureCLI' ? azCliVersion : null + containerSettings: empty(containerGroupName) ? null : containerSettings + arguments: arguments + environmentVariables: empty(environmentVariables) ? null : environmentVariables + scriptContent: empty(scriptContent) ? null : scriptContent + primaryScriptUri: empty(primaryScriptUri) ? null : primaryScriptUri + supportingScriptUris: empty(supportingScriptUris) ? null : supportingScriptUris + cleanupPreference: cleanupPreference + forceUpdateTag: runOnce ? resourceGroup().name : baseTime + retentionInterval: retentionInterval + timeout: timeout + } +} + +resource deploymentScript_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${deploymentScript.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: deploymentScript +} + +@description('The resource ID of the deployment script') +output resourceId string = deploymentScript.id + +@description('The resource group the deployment script was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployment script') +output name string = deploymentScript.name + +@description('outputs from the script') +output outputs object = deploymentScript.properties.outputs.avdObjectId diff --git a/carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep b/carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep new file mode 100644 index 000000000..f2f5b2a9b --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep @@ -0,0 +1,130 @@ +@description('Required. Display name of the script to be run.') +param name string + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Type of the script. AzurePowerShell, AzureCLI.') +@allowed([ + 'AzurePowerShell' + 'AzureCLI' +]) +param kind string = 'AzurePowerShell' + +@description('Optional. Azure PowerShell module version to be used.') +param azPowerShellVersion string = '3.0' + +@description('Optional. Azure CLI module version to be used.') +param azCliVersion string = '' + +@description('Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead.') +param scriptContent string = '' + +@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead.') +param primaryScriptUri string = '' + +@description('Optional. The environment variables to pass over to the script. Must have a \'name\' and a \'value\' or a \'secretValue\' property.') +param environmentVariables array = [] + +@description('Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent).') +param supportingScriptUris array = [] + +@description('Optional. Command-line arguments to pass to the script. Arguments are separated by spaces.') +param arguments string = '' + +@description('Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week).') +param retentionInterval string = 'P1D' + +@description('Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once.') +param runOnce bool = false + +@description('Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled).') +@allowed([ + 'Always' + 'OnSuccess' + 'OnExpiration' +]) +param cleanupPreference string = 'Always' + +@description('Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a \'containerGroupName\' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use \'containerGroupName\' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. \'containerGroupName\' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed.') +param containerGroupName string = '' + +@description('Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; \'PT30M\' - 30 minutes; \'P5D\' - 5 days; \'P1Y\' 1 year.') +param timeout string = 'PT6H' + +@description('Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var containerSettings = { + containerGroupName: containerGroupName +} + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: name + location: location + tags: tags + identity: identity + kind: any(kind) + properties: { + azPowerShellVersion: kind == 'AzurePowerShell' ? azPowerShellVersion : null + azCliVersion: kind == 'AzureCLI' ? azCliVersion : null + containerSettings: empty(containerGroupName) ? null : containerSettings + arguments: arguments + environmentVariables: empty(environmentVariables) ? null : environmentVariables + scriptContent: empty(scriptContent) ? null : scriptContent + primaryScriptUri: empty(primaryScriptUri) ? null : primaryScriptUri + supportingScriptUris: empty(supportingScriptUris) ? null : supportingScriptUris + cleanupPreference: cleanupPreference + forceUpdateTag: runOnce ? resourceGroup().name : baseTime + retentionInterval: retentionInterval + timeout: timeout + } +} + +resource deploymentScript_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${deploymentScript.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: deploymentScript +} + +@description('The resource ID of the deployment script') +output resourceId string = deploymentScript.id + +@description('The resource group the deployment script was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployment script') +output name string = deploymentScript.name + diff --git a/carml/1.0.0/Microsoft.Resources/deploymentScripts/readme.md b/carml/1.0.0/Microsoft.Resources/deploymentScripts/readme.md new file mode 100644 index 000000000..c1cf19768 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/readme.md @@ -0,0 +1,82 @@ +# Deployment Scripts `[Microsoft.Resources/deploymentScripts]` + +This module deploys a deployment script. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Resources/deploymentScripts` | 2020-10-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `arguments` | string | | | Optional. Command-line arguments to pass to the script. Arguments are separated by spaces. | +| `azCliVersion` | string | | | Optional. Azure CLI module version to be used. | +| `azPowerShellVersion` | string | `3.0` | | Optional. Azure PowerShell module version to be used. | +| `baseTime` | string | `[utcNow('yyyy-MM-dd-HH-mm-ss')]` | | Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed. | +| `cleanupPreference` | string | `Always` | `[Always, OnSuccess, OnExpiration]` | Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled). | +| `containerGroupName` | string | | | Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `environmentVariables` | array | `[]` | | Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property. | +| `kind` | string | `AzurePowerShell` | `[AzurePowerShell, AzureCLI]` | Optional. Type of the script. AzurePowerShell, AzureCLI. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Display name of the script to be run. | +| `primaryScriptUri` | string | | | Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead. | +| `retentionInterval` | string | `P1D` | | Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week). | +| `runOnce` | bool | | | Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once. | +| `scriptContent` | string | | | Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead. | +| `supportingScriptUris` | array | `[]` | | Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent). | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `timeout` | string | `PT1H` | | Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployment script | +| `resourceGroupName` | string | The resource group the deployment script was deployed into | +| `resourceId` | string | The resource ID of the deployment script | + +## Considerations + +This module requires a User Assigned Identity (MSI, managed service identity) to exist, and this MSI has to have contributor rights on the subscription - that allows the Deployment Script to create the required Storage Account and the Azure Container Instance. + +## Template references + +- [Deploymentscripts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2020-10-01/deploymentScripts) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.0/Microsoft.Resources/deploymentScripts/version.json b/carml/1.0.0/Microsoft.Resources/deploymentScripts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/deploymentScripts/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/carml/1.0.0/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep b/carml/1.0.0/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep new file mode 100644 index 000000000..c3f891565 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep @@ -0,0 +1,31 @@ +@description('Optional. The name of the Lock') +param name string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Set lock level.') +param level string = 'NotSpecified' + +var lockNotes = { + CanNotDelete: 'Cannot delete resource or child resources.' + ReadOnly: 'Cannot modify the resource or child resources.' +} + +var lockName = empty(name) ? '${level}-lock' : name + +resource lock 'Microsoft.Authorization/locks@2017-04-01' = if (level != 'NotSpecified') { + name: lockName + properties: { + level: level + notes: lockNotes[level] + } +} + +@description('The resource ID of the lock') +output resourceId string = lock.id + +@description('The name of the lock') +output name string = lock.name diff --git a/carml/1.0.0/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..746874f92 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,187 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceGroupName string + +var builtInRoleNames = { + 'AcrDelete': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11') + 'AcrImageSigner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'AcrPush': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec') + 'AcrQuarantineReader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04') + 'AcrQuarantineWriter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608') + 'API Management Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c') + 'API Management Service Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61') + 'API Management Service Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d') + 'App Configuration Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b') + 'App Configuration Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Application Insights Snapshot Debugger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b') + 'Attestation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e') + 'Attestation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3') + 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') + 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') + 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Azure Connected Machine Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7') + 'Azure Connected Machine Resource Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302') + 'Azure Digital Twins Owner (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe') + 'Azure Digital Twins Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8') + 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f') + 'Azure Kubernetes Service Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8') + 'Azure Maps Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204') + 'Azure Maps Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa') + 'Azure Sentinel Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade') + 'Azure Sentinel Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb') + 'Azure Sentinel Responder': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Azure Stack Registration Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Billing Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64') + 'BizTalk Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342') + 'Blockchain Member Node Access (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24') + 'Blueprint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4') + 'Blueprint Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090') + 'CDN Endpoint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45') + 'CDN Endpoint Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd') + 'CDN Profile Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432') + 'CDN Profile Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af') + 'Classic Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f') + 'Classic Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25') + 'Classic Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d') + 'Classic Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb') + 'ClearDB MySQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe') + 'Cognitive Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68') + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3') + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f') + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c') + 'Cognitive Services Custom Vision Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73') + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b') + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c') + 'Cognitive Services QnA Maker Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025') + 'Cognitive Services QnA Maker Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126') + 'Cognitive Services User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Cosmos DB Account Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'CosmosBackupOperator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb') + 'Cost Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430') + 'Cost Management Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3') + 'Data Box Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5') + 'Data Box Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027') + 'Data Factory Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5') + 'Data Lake Analytics Developer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Desktop Virtualization User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'Experimentation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c') + 'Experimentation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c') + 'Experimentation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1') + 'FHIR Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd') + 'FHIR Data Exporter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843') + 'FHIR Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508') + 'FHIR Data Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913') + 'Graph Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9') + 'HDInsight Cluster Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a') + 'HDInsight Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c') + 'Hierarchy Settings Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d') + 'Hybrid Server Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb') + 'Hybrid Server Resource Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624') + 'Integration Service Environment Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8') + 'Integration Service Environment Developer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec') + 'Intelligent Systems Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Knowledge Consumer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c') + 'Kubernetes Cluster - Azure Arc Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41') + 'Lab Creator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Managed Services Registration assignment Delete ': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46') + 'Management Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c') + 'Management Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d') + 'Marketplace Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'New Relic APM Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237') + 'Object Understanding Account Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745') + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Policy Insights Data Writer (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Redis Cache Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17') + 'Remote Rendering Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e') + 'Remote Rendering Client': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Scheduler Job Collections Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94') + 'Search Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0') + 'Security Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd') + 'Security Assessment Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5') + 'Security Manager (Legacy)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10') + 'Security Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4') + 'SignalR AccessKey Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e') + 'SignalR Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') + 'Spatial Anchors Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827') + 'Spatial Anchors Account Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c') + 'Spatial Anchors Account Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413') + 'SQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'SQL Server Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Support Request Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e') + 'Tag Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f') + 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + 'Workbook Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad') + 'Workbook Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d') +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(resourceGroupName, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } +}] diff --git a/carml/1.0.0/Microsoft.Resources/resourceGroups/.parameters/parameters.json b/carml/1.0.0/Microsoft.Resources/resourceGroups/.parameters/parameters.json new file mode 100644 index 000000000..3be494132 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/resourceGroups/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rg-x-001" + }, + "tags": { + "value": { + "Test": "Yes" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep b/carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep new file mode 100644 index 000000000..0327349f7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep @@ -0,0 +1,53 @@ +targetScope = 'subscription' + +@description('Required. The name of the Resource Group') +param name string + +@description('Optional. Location of the Resource Group. It uses the deployment\'s location when not provided.') +param location string = deployment().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the storage account resource.') +param tags object = {} + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2019-05-01' = { + location: location + name: name + tags: tags + properties: {} +} + +module resourceGroup_lock '.bicep/nested_lock.bicep' = if (lock != 'NotSpecified') { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-RG-${lock}-Lock' + params: { + name: '${resourceGroup.name}-${lock}-lock' + level: lock + } +} + +module resourceGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RG-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceGroupName: resourceGroup.name + } + scope: resourceGroup +}] + +@description('The name of the resource group') +output name string = resourceGroup.name + +@description('The resource ID of the resource group') +output resourceId string = resourceGroup.id diff --git a/carml/1.0.0/Microsoft.Resources/resourceGroups/readme.md b/carml/1.0.0/Microsoft.Resources/resourceGroups/readme.md new file mode 100644 index 000000000..a823c6416 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/resourceGroups/readme.md @@ -0,0 +1,77 @@ +# Resource Groups `[Microsoft.Resources/resourceGroups]` + +This module deploys a resource group. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Resources/resourceGroups` | 2019-05-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `location` | string | `[deployment().location]` | | Optional. Location of the Resource Group. It uses the deployment's location when not provided. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the Resource Group | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the storage account resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Considerations + +This module requires a User Assigned Identity (MSI, managed service identity) to exist, and this MSI has to have contributor rights on the subscription - that allows the Deployment Script to create the required Storage Account and the Azure Container Instance. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the resource group | +| `resourceId` | string | The resource ID of the resource group | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Resourcegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-05-01/resourceGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Resources/resourceGroups/version.json b/carml/1.0.0/Microsoft.Resources/resourceGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/resourceGroups/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/carml/1.0.0/Microsoft.Resources/tags/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Resources/tags/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.0/Microsoft.Resources/tags/.parameters/rg.parameters.json b/carml/1.0.0/Microsoft.Resources/tags/.parameters/rg.parameters.json new file mode 100644 index 000000000..a90e2e5b2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/.parameters/rg.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "onlyUpdate": { + "value": false + }, + "tags": { + "value": { + "Test": "Yes", + "TestToo": "No" + } + }, + "resourceGroupName": { + "value": "validation-rg" + } + } +} diff --git a/carml/1.0.0/Microsoft.Resources/tags/.parameters/sub.parameters.json b/carml/1.0.0/Microsoft.Resources/tags/.parameters/sub.parameters.json new file mode 100644 index 000000000..840b23ba6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/.parameters/sub.parameters.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "onlyUpdate": { + "value": true + }, + "tags": { + "value": { + "Test": "Yes", + "TestToo": "No" + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Resources/tags/deploy.bicep b/carml/1.0.0/Microsoft.Resources/tags/deploy.bicep new file mode 100644 index 000000000..4b3d6b791 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/deploy.bicep @@ -0,0 +1,36 @@ +targetScope = 'subscription' + +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@description('Optional. Name of the Resource Group to assign the tags to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription.') +param resourceGroupName string = '' + +@description('Optional. Subscription ID of the subscription to assign the tags to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription.') +param subscriptionId string = subscription().id + +module tags_sub 'subscriptions/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${deployment().name}-Tags-Sub' + params: { + onlyUpdate: onlyUpdate + tags: tags + } +} + +module tags_rg 'resourceGroups/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${deployment().name}-Tags-RG' + scope: resourceGroup(resourceGroupName) + params: { + onlyUpdate: onlyUpdate + tags: tags + } +} + +@description('The name of the tags resource') +output name string = (!empty(resourceGroupName) && !empty(subscriptionId)) ? tags_rg.outputs.name : tags_sub.outputs.name + +@description('The applied tags') +output tags object = (!empty(resourceGroupName) && !empty(subscriptionId)) ? tags_rg.outputs.tags : tags_sub.outputs.tags diff --git a/carml/1.0.0/Microsoft.Resources/tags/readme.md b/carml/1.0.0/Microsoft.Resources/tags/readme.md new file mode 100644 index 000000000..6d74aff75 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/readme.md @@ -0,0 +1,46 @@ +# Resources Tags `[Microsoft.Resources/tags]` + +This module deploys Resources Tags on a subscription or resource group scope. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `onlyUpdate` | bool | | | Optional. Instead of overwriting the existing tags, combine them with the new tags | +| `resourceGroupName` | string | | | Optional. Name of the Resource Group to assign the tags to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription. | +| `subscriptionId` | string | `[subscription().id]` | | Optional. Subscription ID of the subscription to assign the tags to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription. | +| `tags` | object | `{object}` | | Optional. Tags for the resource group. If not provided, removes existing tags | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep new file mode 100644 index 000000000..0f3301f97 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep @@ -0,0 +1,9 @@ +@description('Optional. The name of the tags resource.') +param name string = 'default' + +resource tags 'Microsoft.Resources/tags@2019-10-01' existing = { + name: name +} + +@description('Tags currently applied to the subscription level') +output existingTags object = contains(tags.properties, 'tags') ? tags.properties.tags : {} diff --git a/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/deploy.bicep b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/deploy.bicep new file mode 100644 index 000000000..3c06c2b2a --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/deploy.bicep @@ -0,0 +1,33 @@ +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +module readTags '.bicep/readTags.bicep' = if (onlyUpdate) { + name: '${deployment().name}-ReadTags' +} + +var newTags = (onlyUpdate) ? union(readTags.outputs.existingTags, tags) : tags + +resource tag 'Microsoft.Resources/tags@2019-10-01' = { + name: name + properties: { + tags: newTags + } +} + +@description('The name of the tags resource') +output name string = tag.name + +@description('The resourceId of the resource group the tags were applied to') +output resourceId string = resourceGroup().id + +@description('The name of the resource group the tags were applied to') +output resourceGroupName string = resourceGroup().name + +@description('The applied tags') +output tags object = newTags diff --git a/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/readme.md b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/readme.md new file mode 100644 index 000000000..de64be520 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/readme.md @@ -0,0 +1,47 @@ +# Resources Tags ResourceGroups `[Microsoft.Resources/tags/resourceGroups]` + +This module deploys Resources Tags on a resource group scope. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `name` | string | `default` | | Optional. The name of the tags resource. | +| `onlyUpdate` | bool | | | Optional. Instead of overwriting the existing tags, combine them with the new tags | +| `tags` | object | `{object}` | | Optional. Tags for the resource group. If not provided, removes existing tags | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `resourceGroupName` | string | The name of the resource group the tags were applied to | +| `resourceId` | string | The resourceId of the resource group the tags were applied to | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/version.json b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/resourceGroups/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.0/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep new file mode 100644 index 000000000..65b245725 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep @@ -0,0 +1,11 @@ +targetScope = 'subscription' + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +resource tags 'Microsoft.Resources/tags@2019-10-01' existing = { + name: name +} + +@description('Tags currently applied to the subscription level') +output existingTags object = contains(tags.properties, 'tags') ? tags.properties.tags : {} diff --git a/carml/1.0.0/Microsoft.Resources/tags/subscriptions/deploy.bicep b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/deploy.bicep new file mode 100644 index 000000000..37f4759a8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/deploy.bicep @@ -0,0 +1,29 @@ +targetScope = 'subscription' + +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +module readTags '.bicep/readTags.bicep' = if (onlyUpdate) { + name: '${deployment().name}-ReadTags' +} + +var newTags = (onlyUpdate) ? union(readTags.outputs.existingTags, tags) : tags + +resource tag 'Microsoft.Resources/tags@2019-10-01' = { + name: name + properties: { + tags: newTags + } +} + +@description('The name of the tags resource') +output name string = tag.name + +@description('The applied tags') +output tags object = newTags diff --git a/carml/1.0.0/Microsoft.Resources/tags/subscriptions/readme.md b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/readme.md new file mode 100644 index 000000000..fe75bc2b3 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/readme.md @@ -0,0 +1,45 @@ +# Resources Tags Subscriptions `[Microsoft.Resources/tags/subscriptions]` + +This module deploys Resources Tags on a subscription scope. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `name` | string | `default` | | Optional. The name of the tags resource. | +| `onlyUpdate` | bool | | | Optional. Instead of overwriting the existing tags, combine them with the new tags | +| `tags` | object | `{object}` | | Optional. Tags for the resource group. If not provided, removes existing tags | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.0.0/Microsoft.Resources/tags/subscriptions/version.json b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/subscriptions/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.0/Microsoft.Resources/tags/version.json b/carml/1.0.0/Microsoft.Resources/tags/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.0/Microsoft.Resources/tags/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.0/Microsoft.Security/azureSecurityCenter/.bicep/nested_iotSecuritySolutions.bicep b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/.bicep/nested_iotSecuritySolutions.bicep new file mode 100644 index 000000000..5f37462ee --- /dev/null +++ b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/.bicep/nested_iotSecuritySolutions.bicep @@ -0,0 +1,16 @@ +@description('Optional. Security Solution data') +param ioTSecuritySolutionProperties object = {} + +resource iotSecuritySolutions 'Microsoft.Security/iotSecuritySolutions@2019-08-01' = if (!empty(ioTSecuritySolutionProperties)) { + name: 'iotSecuritySolutions' + properties: { + workspace: ioTSecuritySolutionProperties.workspace + displayName: ioTSecuritySolutionProperties.displayName + status: ioTSecuritySolutionProperties.status + export: ioTSecuritySolutionProperties.export + disabledDataSources: ioTSecuritySolutionProperties.disabledDataSources + iotHubs: ioTSecuritySolutionProperties.iotHubs + userDefinedResources: ioTSecuritySolutionProperties.userDefinedResources + recommendationsConfiguration: ioTSecuritySolutionProperties.recommendationsConfiguration + } +} diff --git a/carml/1.0.0/Microsoft.Security/azureSecurityCenter/.parameters/parameters.json b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/.parameters/parameters.json new file mode 100644 index 000000000..cfa02a1dd --- /dev/null +++ b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/.parameters/parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "scope": { + "value": "/subscriptions/<>" + }, + "securityContactProperties": { + "value": { + "email": "foo@contoso.com", + "phone": "+12345678", + "alertNotifications": "Off", + "alertsToAdmins": "Off" + } + }, + "workspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Security/azureSecurityCenter/deploy.bicep b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/deploy.bicep new file mode 100644 index 000000000..84b1ff1b9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/deploy.bicep @@ -0,0 +1,226 @@ +targetScope = 'subscription' + +@description('Required. The full Azure ID of the workspace to save the data in.') +param workspaceId string + +@description('Required. All the VMs in this scope will send their security data to the mentioned workspace unless overridden by a setting with more specific scope.') +param scope string + +@description('Optional. Describes what kind of security agent provisioning action to take. - On or Off') +@allowed([ + 'On' + 'Off' +]) +param autoProvision string = 'On' + +@description('Optional. Device Security group data') +param deviceSecurityGroupProperties object = {} + +@description('Optional. Security Solution data') +param ioTSecuritySolutionProperties object = {} + +@description('Optional. The pricing tier value for VMs. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param virtualMachinesPricingTier string = 'Free' + +@description('Optional. The pricing tier value for SqlServers. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param sqlServersPricingTier string = 'Free' + +@description('Optional. The pricing tier value for AppServices. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param appServicesPricingTier string = 'Free' + +@description('Optional. The pricing tier value for StorageAccounts. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param storageAccountsPricingTier string = 'Free' + +@description('Optional. The pricing tier value for SqlServerVirtualMachines. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param sqlServerVirtualMachinesPricingTier string = 'Free' + +@description('Optional. The pricing tier value for KubernetesService. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param kubernetesServicePricingTier string = 'Free' + +@description('Optional. The pricing tier value for ContainerRegistry. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param containerRegistryPricingTier string = 'Free' + +@description('Optional. The pricing tier value for KeyVaults. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param keyVaultsPricingTier string = 'Free' + +@description('Optional. The pricing tier value for DNS. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param dnsPricingTier string = 'Free' + +@description('Optional. The pricing tier value for ARM. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param armPricingTier string = 'Free' + +@description('Optional. The pricing tier value for OpenSourceRelationalDatabases. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param openSourceRelationalDatabasesTier string = 'Free' + +@description('Optional. Security contact data') +param securityContactProperties object = {} + +resource autoProvisioningSettings 'Microsoft.Security/autoProvisioningSettings@2017-08-01-preview' = { + name: 'default' + properties: { + autoProvision: autoProvision + } +} + +resource deviceSecurityGroups 'Microsoft.Security/deviceSecurityGroups@2019-08-01' = if (!empty(deviceSecurityGroupProperties)) { + name: 'deviceSecurityGroups' + properties: { + thresholdRules: deviceSecurityGroupProperties.thresholdRules + timeWindowRules: deviceSecurityGroupProperties.timeWindowRules + allowlistRules: deviceSecurityGroupProperties.allowlistRules + denylistRules: deviceSecurityGroupProperties.denylistRules + } +} + +module iotSecuritySolutions '.bicep/nested_iotSecuritySolutions.bicep' = if (!empty(ioTSecuritySolutionProperties)) { + name: '${uniqueString(deployment().name)}-ASC-IotSecuritySolutions' + scope: resourceGroup(empty(ioTSecuritySolutionProperties) ? 'dummy' : ioTSecuritySolutionProperties.resourceGroup) + params: { + ioTSecuritySolutionProperties: ioTSecuritySolutionProperties + } +} + +resource VirtualMachinesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'VirtualMachines' + properties: { + pricingTier: virtualMachinesPricingTier + } +} + +resource SqlServersPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'SqlServers' + properties: { + pricingTier: sqlServersPricingTier + } +} + +resource AppServicesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'AppServices' + properties: { + pricingTier: appServicesPricingTier + } +} + +resource StorageAccountsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'StorageAccounts' + properties: { + pricingTier: storageAccountsPricingTier + } +} + +resource SqlServerVirtualMachinesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'SqlServerVirtualMachines' + properties: { + pricingTier: sqlServerVirtualMachinesPricingTier + } +} + +resource KubernetesServicePricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'KubernetesService' + properties: { + pricingTier: kubernetesServicePricingTier + } +} + +resource ContainerRegistryPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'ContainerRegistry' + properties: { + pricingTier: containerRegistryPricingTier + } +} + +resource KeyVaultsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'KeyVaults' + properties: { + pricingTier: keyVaultsPricingTier + } +} + +resource DnsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'Dns' + properties: { + pricingTier: dnsPricingTier + } +} + +resource ArmPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'Arm' + properties: { + pricingTier: armPricingTier + } +} + +resource OpenSourceRelationalDatabasesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'OpenSourceRelationalDatabases' + properties: { + pricingTier: openSourceRelationalDatabasesTier + } +} + +resource securityContacts 'Microsoft.Security/securityContacts@2017-08-01-preview' = if (!empty(securityContactProperties)) { + name: 'securityContacts' + properties: { + email: securityContactProperties.email + phone: securityContactProperties.phone + alertNotifications: securityContactProperties.alertNotifications + alertsToAdmins: securityContactProperties.alertsToAdmins + } +} + +resource workspaceSettings 'Microsoft.Security/workspaceSettings@2017-08-01-preview' = { + name: 'default' + properties: { + workspaceId: workspaceId + scope: scope + } + dependsOn: [ + autoProvisioningSettings + ] +} + +@description('The resource IDs of the used log analytics workspace') +output workspaceId string = workspaceId diff --git a/carml/1.0.0/Microsoft.Security/azureSecurityCenter/readme.md b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/readme.md new file mode 100644 index 000000000..26e893635 --- /dev/null +++ b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/readme.md @@ -0,0 +1,142 @@ +# Azure Security Center `[Microsoft.Security/azureSecurityCenter]` + +This template enables Azure security center - Standard tier by default, could be overridden. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Security/autoProvisioningSettings` | 2017-08-01-preview | +| `Microsoft.Security/deviceSecurityGroups` | 2019-08-01 | +| `Microsoft.Security/iotSecuritySolutions` | 2019-08-01 | +| `Microsoft.Security/pricings` | 2018-06-01 | +| `Microsoft.Security/securityContacts` | 2017-08-01-preview | +| `Microsoft.Security/workspaceSettings` | 2017-08-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appServicesPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for AppServices. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `armPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for ARM. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `autoProvision` | string | `On` | `[On, Off]` | Optional. Describes what kind of security agent provisioning action to take. - On or Off | +| `containerRegistryPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for ContainerRegistry. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `deviceSecurityGroupProperties` | object | `{object}` | | Optional. Device Security group data | +| `dnsPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for DNS. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `ioTSecuritySolutionProperties` | object | `{object}` | | Optional. Security Solution data | +| `keyVaultsPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for KeyVaults. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `kubernetesServicePricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for KubernetesService. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `openSourceRelationalDatabasesTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for OpenSourceRelationalDatabases. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `scope` | string | | | Required. All the VMs in this scope will send their security data to the mentioned workspace unless overridden by a setting with more specific scope. | +| `securityContactProperties` | object | `{object}` | | Optional. Security contact data | +| `sqlServersPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for SqlServers. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `sqlServerVirtualMachinesPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for SqlServerVirtualMachines. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `storageAccountsPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for StorageAccounts. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `virtualMachinesPricingTier` | string | `Free` | `[Free, Standard]` | Optional. The pricing tier value for VMs. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `workspaceId` | string | | | Required. The full Azure ID of the workspace to save the data in. | + +### Parameter Usage: `deviceSecurityGroupProperties` + +```json +"deviceSecurityGroupProperties": { + "value": { + "thresholdRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "minThreshold": "integer", + "maxThreshold": "integer" + } + ], + "timeWindowRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "minThreshold": "integer", + "maxThreshold": "integer", + "timeWindowSize": "string" + } + ], + "allowlistRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "allowlistValues": [ + "string" + ] + } + ], + "denylistRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "denylistValues": [ + "string" + ] + } + ] + } +} +``` + +### Parameter Usage: `ioTSecuritySolutionProperties` + +```json +"ioTSecuritySolutionProperties": { + "value": { + "resourceGroup": "string", + "workspace": "string", + "displayName": "string", + "status": "string", + "export": [ + "RawEvents" + ], + "disabledDataSources": [ + "TwinData" + ], + "iotHubs": [ + "string" + ], + "userDefinedResources": { + "query": "string", + "querySubscriptions": [ + "string" + ] + }, + "recommendationsConfiguration": [ + { + "recommendationType": "string", + "status": "string" + } + ] + } +} +``` + +### Parameter Usage: `securityContactProperties` + +```json +"securityContactProperties": { + "value": { + "email": "test@contoso.com", + "phone": "+12345678", + "alertNotifications": "On", + "alertsToAdmins": "Off" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `workspaceId` | string | The resource IDs of the used log analytics workspace | + +## Template references + +- [Autoprovisioningsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2017-08-01-preview/autoProvisioningSettings) +- [Devicesecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2019-08-01/deviceSecurityGroups) +- [Iotsecuritysolutions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2019-08-01/iotSecuritySolutions) +- [Pricings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2018-06-01/pricings) +- [Securitycontacts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2017-08-01-preview/securityContacts) +- [Workspacesettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2017-08-01-preview/workspaceSettings) diff --git a/carml/1.0.0/Microsoft.Security/azureSecurityCenter/version.json b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Security/azureSecurityCenter/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_privateEndpoints.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_privateEndpoints.bicep new file mode 100644 index 000000000..d1381aa57 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_privateEndpoints.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpoint object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpoint, 'name') ? (empty(privateEndpoint.name) ? '${privateEndpointResourceName}-${privateEndpoint.service}' : privateEndpoint.name) : '${privateEndpointResourceName}-${privateEndpoint.service}' + subnetResourceId: privateEndpoint.subnetResourceId + service: [ + privateEndpoint.service + ] + privateDnsZoneResourceIds: contains(privateEndpoint, 'privateDnsZoneResourceIds') ? (empty(privateEndpoint.privateDnsZoneResourceIds) ? [] : privateEndpoint.privateDnsZoneResourceIds) : [] + customDnsConfigs: contains(privateEndpoint, 'customDnsConfigs') ? (empty(privateEndpoint.customDnsConfigs) ? null : privateEndpoint.customDnsConfigs) : null +} + +resource privateEndpoint_name 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateEndpoint_name_default 'privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: 'default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + } +} diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..be578a364 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(namespace.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: namespace +}] diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/.parameters/parameters.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.parameters/parameters.json new file mode 100644 index 000000000..6a1694eee --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/.parameters/parameters.json @@ -0,0 +1,156 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sbn-x-002" + }, + "skuName": { + "value": "Premium" + }, + "tags": { + "value": {} + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "disasterRecoveryConfigs": { + "value": {} + }, + "migrationConfigurations": { + "value": {} + }, + "virtualNetworkRules": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-003" + ] + }, + "ipFilterRules": { + "value": [ + { + "filterName": "ipFilter1", + "ipMask": "10.0.1.0/32", + "action": "Accept" + }, + { + "filterName": "ipFilter2", + "ipMask": "10.0.2.0/32", + "action": "Accept" + } + ] + }, + "authorizationRules": { + "value": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + }, + "queues": { + "value": [ + { + "name": "<>-az-sbq-x-002", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "authorizationRules": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + } + ] + }, + "topics": { + "value": [ + { + "name": "<>-az-sbt-x-001", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "authorizationRules": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/deploy.bicep new file mode 100644 index 000000000..7df7ce331 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/deploy.bicep @@ -0,0 +1,44 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. The name of the authorization rule') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource authorizationRule 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2017-04-01' = { + name: name + parent: namespace + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/readme.md new file mode 100644 index 000000000..391219c3f --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/readme.md @@ -0,0 +1,30 @@ +# ServiceBus Namespace Authorization Rules `[Microsoft.ServiceBus/namespaces/authorizationRules]` + +This module deploys authorization rules for a service bus namespace + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/AuthorizationRules` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. The name of the authorization rule | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | Optional. The rights associated with the rule. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/AuthorizationRules) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/authorizationRules/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/deploy.bicep new file mode 100644 index 000000000..85d095fc1 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/deploy.bicep @@ -0,0 +1,322 @@ +@description('Optional. Name of the Service Bus Namespace. If no name is provided, then unique name will be created.') +@maxLength(50) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Name of this SKU. - Basic, Standard, Premium') +@allowed([ + 'Basic' + 'Standard' + 'Premium' +]) +param skuName string = 'Basic' + +@description('Optional. Enabling this property creates a Premium Service Bus Namespace in regions supported availability zones.') +param zoneRedundant bool = false + +@description('Optional. Authorization Rules for the Service Bus namespace') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. IP Filter Rules for the Service Bus namespace') +param ipFilterRules array = [] + +@description('Optional. The migration configuration.') +param migrationConfigurations object = {} + +@description('Optional. The disaster recovery configuration.') +param disasterRecoveryConfigs object = {} + +@description('Optional. vNet Rules SubnetIds for the Service Bus namespace.') +param virtualNetworkRules array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The queues to create in the service bus namespace') +param queues array = [] + +@description('Optional. The topics to create in the service bus namespace') +param topics array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'OperationalLogs' +]) +param logsToEnable array = [ + 'OperationalLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var maxNameLength = 50 +var uniqueServiceBusNamespaceNameUntrim = uniqueString('Service Bus Namespace${baseTime}') +var uniqueServiceBusNamespaceName = ((length(uniqueServiceBusNamespaceNameUntrim) > maxNameLength) ? substring(uniqueServiceBusNamespaceNameUntrim, 0, maxNameLength) : uniqueServiceBusNamespaceNameUntrim) + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' = { + name: !empty(name) ? name : uniqueServiceBusNamespaceName + location: location + tags: empty(tags) ? null : tags + sku: { + name: skuName + } + identity: identity + properties: { + zoneRedundant: zoneRedundant + } +} + +module serviceBusNamespace_disasterRecoveryConfig 'disasterRecoveryConfigs/deploy.bicep' = if (!empty(disasterRecoveryConfigs)) { + name: '${uniqueString(deployment().name, location)}-DisasterRecoveryConfig' + params: { + namespaceName: serviceBusNamespace.name + name: contains(disasterRecoveryConfigs, 'name') ? disasterRecoveryConfigs.name : 'default' + alternateName: contains(disasterRecoveryConfigs, 'alternateName') ? disasterRecoveryConfigs.alternateName : '' + partnerNamespaceResourceID: contains(disasterRecoveryConfigs, 'partnerNamespace') ? disasterRecoveryConfigs.partnerNamespace : '' + } +} + +module serviceBusNamespace_migrationConfigurations 'migrationConfigurations/deploy.bicep' = if (!empty(migrationConfigurations)) { + name: '${uniqueString(deployment().name, location)}-MigrationConfigurations' + params: { + namespaceName: serviceBusNamespace.name + name: contains(migrationConfigurations, 'name') ? migrationConfigurations.name : '$default' + postMigrationName: migrationConfigurations.postMigrationName + targetNamespaceResourceId: migrationConfigurations.targetNamespace + } +} + +module serviceBusNamespace_virtualNetworkRules 'virtualNetworkRules/deploy.bicep' = [for (virtualNetworkRule, index) in virtualNetworkRules: { + name: '${uniqueString(deployment().name, location)}-VirtualNetworkRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: last(split(virtualNetworkRule, '/')) + virtualNetworkSubnetId: virtualNetworkRule + } +}] + +module serviceBusNamespace_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-AuthorizationRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module serviceBusNamespace_ipFilterRules 'ipFilterRules/deploy.bicep' = [for (ipFilterRule, index) in ipFilterRules: { + name: '${uniqueString(deployment().name, location)}-IpFilterRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: contains(ipFilterRule, 'name') ? ipFilterRule.name : ipFilterRule.filterName + action: ipFilterRule.action + filterName: ipFilterRule.filterName + ipMask: ipFilterRule.ipMask + } +}] + +module serviceBusNamespace_queues 'queues/deploy.bicep' = [for (queue, index) in queues: { + name: '${uniqueString(deployment().name, location)}-Queue-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: queue.name + authorizationRules: contains(queue, 'authorizationRules') ? queue.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + deadLetteringOnMessageExpiration: contains(queue, 'deadLetteringOnMessageExpiration') ? queue.deadLetteringOnMessageExpiration : true + defaultMessageTimeToLive: contains(queue, 'defaultMessageTimeToLive') ? queue.defaultMessageTimeToLive : 'P14D' + duplicateDetectionHistoryTimeWindow: contains(queue, 'duplicateDetectionHistoryTimeWindow') ? queue.duplicateDetectionHistoryTimeWindow : 'PT10M' + enableBatchedOperations: contains(queue, 'enableBatchedOperations') ? queue.enableBatchedOperations : true + enableExpress: contains(queue, 'enableExpress') ? queue.enableExpress : false + enablePartitioning: contains(queue, 'enablePartitioning') ? queue.enablePartitioning : false + lock: contains(queue, 'lock') ? queue.lock : 'NotSpecified' + lockDuration: contains(queue, 'lockDuration') ? queue.lockDuration : 'PT1M' + maxDeliveryCount: contains(queue, 'maxDeliveryCount') ? queue.maxDeliveryCount : 10 + maxSizeInMegabytes: contains(queue, 'maxSizeInMegabytes') ? queue.maxSizeInMegabytes : 1024 + requiresDuplicateDetection: contains(queue, 'requiresDuplicateDetection') ? queue.requiresDuplicateDetection : false + requiresSession: contains(queue, 'requiresSession') ? queue.requiresSession : false + roleAssignments: contains(queue, 'roleAssignments') ? queue.roleAssignments : [] + status: contains(queue, 'status') ? queue.status : 'Active' + } +}] + +module serviceBusNamespace_topics 'topics/deploy.bicep' = [for (topic, index) in topics: { + name: '${uniqueString(deployment().name, location)}-Topic-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: topic.name + authorizationRules: contains(topic, 'authorizationRules') ? topic.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + autoDeleteOnIdle: contains(topic, 'autoDeleteOnIdle') ? topic.autoDeleteOnIdle : 'PT5M' + defaultMessageTimeToLive: contains(topic, 'defaultMessageTimeToLive') ? topic.defaultMessageTimeToLive : 'P14D' + duplicateDetectionHistoryTimeWindow: contains(topic, 'duplicateDetectionHistoryTimeWindow') ? topic.duplicateDetectionHistoryTimeWindow : 'PT10M' + enableBatchedOperations: contains(topic, 'enableBatchedOperations') ? topic.enableBatchedOperations : true + enableExpress: contains(topic, 'enableExpress') ? topic.enableExpress : false + enablePartitioning: contains(topic, 'enablePartitioning') ? topic.enablePartitioning : false + lock: contains(topic, 'lock') ? topic.lock : 'NotSpecified' + maxMessageSizeInKilobytes: contains(topic, 'maxMessageSizeInKilobytes') ? topic.maxMessageSizeInKilobytes : 1024 + maxSizeInMegabytes: contains(topic, 'maxSizeInMegabytes') ? topic.maxSizeInMegabytes : 1024 + requiresDuplicateDetection: contains(topic, 'requiresDuplicateDetection') ? topic.requiresDuplicateDetection : false + roleAssignments: contains(topic, 'roleAssignments') ? topic.roleAssignments : [] + status: contains(topic, 'status') ? topic.status : 'Active' + supportOrdering: contains(topic, 'supportOrdering') ? topic.supportOrdering : false + } +}] + +resource serviceBusNamespace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${serviceBusNamespace.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: serviceBusNamespace +} + +resource serviceBusNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${serviceBusNamespace.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: serviceBusNamespace +} + +module serviceBusNamespace_privateEndpoints '.bicep/nested_privateEndpoints.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: serviceBusNamespace.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpoint: privateEndpoint + tags: tags + } +}] + +module serviceBusNamespace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: serviceBusNamespace.id + } +}] + +@description('The resource ID of the deployed service bus namespace') +output resourceId string = serviceBusNamespace.id + +@description('The resource group of the deployed service bus namespace') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed service bus namespace') +output name string = serviceBusNamespace.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(serviceBusNamespace.identity, 'principalId') ? serviceBusNamespace.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/deploy.bicep new file mode 100644 index 000000000..bc8478a0a --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/deploy.bicep @@ -0,0 +1,43 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the disaster recovery config') +param name string = 'default' + +@description('Optional. Primary/Secondary eventhub namespace name, which is part of GEO DR pairing') +param alternateName string = '' + +@description('Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing') +param partnerNamespaceResourceID string = '' + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource disasterRecoveryConfig 'Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs@2017-04-01' = { + name: name + parent: namespace + properties: { + alternateName: alternateName + partnerNamespace: partnerNamespaceResourceID + } +} + +@description('The name of the disaster recovery config.') +output name string = disasterRecoveryConfig.name + +@description('The Resource ID of the disaster recovery config.') +output resourceId string = disasterRecoveryConfig.id + +@description('The name of the Resource Group the disaster recovery config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/readme.md new file mode 100644 index 000000000..7d8cd5c02 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/readme.md @@ -0,0 +1,31 @@ +# Service Bus Namespace Disaster Recovery Config `[Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs]` + +This module deploys a disaster recovery config for a service bus Namespace + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `alternateName` | string | | | Optional. Primary/Secondary eventhub namespace name, which is part of GEO DR pairing | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `default` | | Optional. The name of the disaster recovery config | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `partnerNamespaceResourceID` | string | | | Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disaster recovery config. | +| `resourceGroupName` | string | The name of the Resource Group the disaster recovery config was created in. | +| `resourceId` | string | The Resource ID of the disaster recovery config. | + +## Template references + +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/disasterRecoveryConfigs) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/deploy.bicep new file mode 100644 index 000000000..9acb32dad --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the ip filter rule') +param name string = filterName + +@description('Required. The IP Filter Action') +@allowed([ + 'Accept' + // 'Reject' # Reason: Only Accept IpFilterRules are accepted by API +]) +param action string + +@description('Required. IP Filter name') +param filterName string + +@description('Required. IP Mask') +param ipMask string + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource ipFilterRule 'Microsoft.ServiceBus/namespaces/ipFilterRules@2018-01-01-preview' = { + name: name + parent: namespace + properties: { + action: action + filterName: filterName + ipMask: ipMask + } +} + +@description('The name of the IP filter rule.') +output name string = ipFilterRule.name + +@description('The Resource ID of the IP filter rule.') +output resourceId string = ipFilterRule.id + +@description('The name of the Resource Group the IP filter rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/readme.md new file mode 100644 index 000000000..e45eaa35c --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/readme.md @@ -0,0 +1,32 @@ +# ServiceBus Namespace Ip-Filter Rules `[Microsoft.ServiceBus/namespaces/ipFilterRules]` + +This module deploys IP filter rules for a service bus namespace + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/ipfilterrules` | 2018-01-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `action` | string | | `[Accept]` | Required. The IP Filter Action | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `filterName` | string | | | Required. IP Filter name | +| `ipMask` | string | | | Required. IP Mask | +| `name` | string | `[parameters('filterName')]` | | Optional. The name of the ip filter rule | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Queue. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the IP filter rule. | +| `resourceGroupName` | string | The name of the Resource Group the IP filter rule was created in. | +| `resourceId` | string | The Resource ID of the IP filter rule. | + +## Template references + +- [Namespaces/Ipfilterrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/ipfilterrules) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/ipFilterRules/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/deploy.bicep new file mode 100644 index 000000000..e17e03e70 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/deploy.bicep @@ -0,0 +1,43 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the migration configuration') +param name string = '$default' + +@description('Required. Name to access Standard Namespace after migration') +param postMigrationName string + +@description('Required. Existing premium Namespace resource ID which has no entities, will be used for migration') +param targetNamespaceResourceId string + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource migrationConfiguration 'Microsoft.ServiceBus/namespaces/migrationConfigurations@2017-04-01' = { + name: name + parent: namespace + properties: { + targetNamespace: targetNamespaceResourceId + postMigrationName: postMigrationName + } +} + +@description('The name of the migration configuration.') +output name string = migrationConfiguration.name + +@description('The Resource ID of the migration configuration') +output resourceId string = migrationConfiguration.id + +@description('The name of the Resource Group the migration configuration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/readme.md new file mode 100644 index 000000000..ab319b323 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/readme.md @@ -0,0 +1,31 @@ +# ServiceBus Namespace Migration Configuration `[Microsoft.ServiceBus/namespaces/migrationConfigurations]` + +This module deploys a migration configuration for a service bus namespace + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/migrationConfigurations` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `$default` | | Optional. The name of the migration configuration | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `postMigrationName` | string | | | Required. Name to access Standard Namespace after migration | +| `targetNamespaceResourceId` | string | | | Required. Existing premium Namespace resource ID which has no entities, will be used for migration | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the migration configuration. | +| `resourceGroupName` | string | The name of the Resource Group the migration configuration was created in. | +| `resourceId` | string | The Resource ID of the migration configuration | + +## Template references + +- [Namespaces/Migrationconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/migrationConfigurations) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/migrationConfigurations/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e527921f3 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource queue 'Microsoft.ServiceBus/namespaces/queues@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssigment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queue.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: queue +}] diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/deploy.bicep new file mode 100644 index 000000000..2b7831e8b --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/deploy.bicep @@ -0,0 +1,49 @@ +@description('Required. The name of the service bus namepace queue') +param name string + +@description('Required. The name of the parent service bus namespace') +param namespaceName string + +@description('Required. The name of the parent service bus namespace queue') +param queueName string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource queue 'queues@2021-06-01-preview' existing = { + name: queueName + } +} + +resource authorizationRule 'Microsoft.ServiceBus/namespaces/queues/authorizationRules@2017-04-01' = { + name: name + parent: namespace::queue + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The Resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/readme.md new file mode 100644 index 000000000..6a777d4c9 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/readme.md @@ -0,0 +1,31 @@ +# ServiceBus Namespace Queue Authorization Rules `[Microsoft.ServiceBus/namespaces/queues/authorizationRules]` + +This module deploys an authorization rule for a service bus namespace queue. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/queues/authorizationRules` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. The name of the service bus namepace queue | +| `namespaceName` | string | | | Required. The name of the parent service bus namespace | +| `queueName` | string | | | Required. The name of the parent service bus namespace queue | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | Optional. The rights associated with the rule. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The Resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Queues/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/queues/authorizationRules) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/authorizationRules/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/deploy.bicep new file mode 100644 index 000000000..e7c66ed6c --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/deploy.bicep @@ -0,0 +1,149 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. Name of the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param name string + +@description('Optional. ISO 8601 timespan duration of a peek-lock; that is, the amount of time that the message is locked for other receivers. The maximum value for LockDuration is 5 minutes; the default value is 1 minute.') +param lockDuration string = 'PT1M' + +@description('Optional. The maximum size of the queue in megabytes, which is the size of memory allocated for the queue. Default is 1024.') +param maxSizeInMegabytes int = 1024 + +@description('Optional. A value indicating if this queue requires duplicate detection.') +param requiresDuplicateDetection bool = false + +@description('Optional. A value that indicates whether the queue supports the concept of sessions.') +param requiresSession bool = false + +@description('Optional. ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself.') +param defaultMessageTimeToLive string = 'P14D' + +@description('Optional. A value that indicates whether this queue has dead letter support when a message expires.') +param deadLetteringOnMessageExpiration bool = true + +@description('Optional. Value that indicates whether server-side batched operations are enabled.') +param enableBatchedOperations bool = true + +@description('Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes.') +param duplicateDetectionHistoryTimeWindow string = 'PT10M' + +@description('Optional. The maximum delivery count. A message is automatically deadlettered after this number of deliveries. default value is 10.') +param maxDeliveryCount int = 10 + +@description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown') +@allowed([ + 'Active' + 'Disabled' + 'Restoring' + 'SendDisabled' + 'ReceiveDisabled' + 'Creating' + 'Deleting' + 'Renaming' + 'Unknown' +]) +param status string = 'Active' + +@description('Optional. A value that indicates whether the queue is to be partitioned across multiple message brokers.') +param enablePartitioning bool = false + +@description('Optional. A value that indicates whether Express Entities are enabled. An express queue holds a message in memory temporarily before writing it to persistent storage.') +param enableExpress bool = false + +@description('Optional. Authorization Rules for the Service Bus Queue') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + } +] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource queue 'Microsoft.ServiceBus/namespaces/queues@2021-06-01-preview' = { + name: name + parent: namespace + properties: { + lockDuration: lockDuration + maxSizeInMegabytes: maxSizeInMegabytes + requiresDuplicateDetection: requiresDuplicateDetection + requiresSession: requiresSession + defaultMessageTimeToLive: defaultMessageTimeToLive + deadLetteringOnMessageExpiration: deadLetteringOnMessageExpiration + enableBatchedOperations: enableBatchedOperations + duplicateDetectionHistoryTimeWindow: duplicateDetectionHistoryTimeWindow + maxDeliveryCount: maxDeliveryCount + status: status + enablePartitioning: enablePartitioning + enableExpress: enableExpress + } +} + +module queue_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + queueName: queue.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +resource queue_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${queue.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: queue +} + +module queue_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: queue.id + } +}] + +@description('The name of the deployed queue') +output name string = queue.name + +@description('The resource ID of the deployed queue') +output resourceId string = queue.id + +@description('The resource group of the deployed queue') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/readme.md new file mode 100644 index 000000000..9ed183384 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/readme.md @@ -0,0 +1,72 @@ +# ServiceBus Namespace Queue `[Microsoft.ServiceBus/namespaces/queues]` + +This module deploys a queue for a service bus namespace. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ServiceBus/namespaces/queues` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/queues/authorizationRules` | 2017-04-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Optional. Authorization Rules for the Service Bus Queue | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `deadLetteringOnMessageExpiration` | bool | `True` | | Optional. A value that indicates whether this queue has dead letter support when a message expires. | +| `defaultMessageTimeToLive` | string | `P14D` | | Optional. ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself. | +| `duplicateDetectionHistoryTimeWindow` | string | `PT10M` | | Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes. | +| `enableBatchedOperations` | bool | `True` | | Optional. Value that indicates whether server-side batched operations are enabled. | +| `enableExpress` | bool | | | Optional. A value that indicates whether Express Entities are enabled. An express queue holds a message in memory temporarily before writing it to persistent storage. | +| `enablePartitioning` | bool | | | Optional. A value that indicates whether the queue is to be partitioned across multiple message brokers. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `lockDuration` | string | `PT1M` | | Optional. ISO 8601 timespan duration of a peek-lock; that is, the amount of time that the message is locked for other receivers. The maximum value for LockDuration is 5 minutes; the default value is 1 minute. | +| `maxDeliveryCount` | int | `10` | | Optional. The maximum delivery count. A message is automatically deadlettered after this number of deliveries. default value is 10. | +| `maxSizeInMegabytes` | int | `1024` | | Optional. The maximum size of the queue in megabytes, which is the size of memory allocated for the queue. Default is 1024. | +| `name` | string | | | Required. Name of the Service Bus Queue. | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `requiresDuplicateDetection` | bool | | | Optional. A value indicating if this queue requires duplicate detection. | +| `requiresSession` | bool | | | Optional. A value that indicates whether the queue supports the concept of sessions. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `status` | string | `Active` | `[Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown]` | Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed queue | +| `resourceGroupName` | string | The resource group of the deployed queue | +| `resourceId` | string | The resource ID of the deployed queue | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/queues) +- [Namespaces/Queues/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/queues/authorizationRules) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/queues/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/readme.md new file mode 100644 index 000000000..db74d5b38 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/readme.md @@ -0,0 +1,169 @@ +# Service Bus Namespaces `[Microsoft.ServiceBus/namespaces]` + +This module deploys a service bus namespace resource. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.ServiceBus/namespaces` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/AuthorizationRules` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/ipfilterrules` | 2018-01-01-preview | +| `Microsoft.ServiceBus/namespaces/migrationConfigurations` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/queues` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/queues/authorizationRules` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/topics` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/topics/authorizationRules` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/virtualnetworkrules` | 2018-01-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Optional. Authorization Rules for the Service Bus namespace | +| `baseTime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `disasterRecoveryConfigs` | _[disasterRecoveryConfigs](disasterRecoveryConfigs/readme.md)_ object | `{object}` | | Optional. The disaster recovery configuration. | +| `ipFilterRules` | _[ipFilterRules](ipFilterRules/readme.md)_ array | `[]` | | Optional. IP Filter Rules for the Service Bus namespace | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[OperationalLogs]` | `[OperationalLogs]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `migrationConfigurations` | _[migrationConfigurations](migrationConfigurations/readme.md)_ object | `{object}` | | Optional. The migration configuration. | +| `name` | string | | | Optional. Name of the Service Bus Namespace. If no name is provided, then unique name will be created. | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `queues` | _[queues](queues/readme.md)_ array | `[]` | | Optional. The queues to create in the service bus namespace | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuName` | string | `Basic` | `[Basic, Standard, Premium]` | Required. Name of this SKU. - Basic, Standard, Premium | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `topics` | _[topics](topics/readme.md)_ array | `[]` | | Optional. The topics to create in the service bus namespace | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `virtualNetworkRules` | _[virtualNetworkRules](virtualNetworkRules/readme.md)_ array | `[]` | | Optional. vNet Rules SubnetIds for the Service Bus namespace. | +| `zoneRedundant` | bool | | | Optional. Enabling this property creates a Premium Service Bus Namespace in regions supported availability zones. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed service bus namespace | +| `resourceGroupName` | string | The resource group of the deployed service bus namespace | +| `resourceId` | string | The resource ID of the deployed service bus namespace | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces) +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/AuthorizationRules) +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/disasterRecoveryConfigs) +- [Namespaces/Ipfilterrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/ipfilterrules) +- [Namespaces/Migrationconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/migrationConfigurations) +- [Namespaces/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/queues) +- [Namespaces/Queues/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/queues/authorizationRules) +- [Namespaces/Topics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics) +- [Namespaces/Topics/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics/authorizationRules) +- [Namespaces/Virtualnetworkrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/virtualnetworkrules) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d022a5864 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource topic 'Microsoft.ServiceBus/namespaces/topics@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssigment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(topic.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: topic +}] diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/deploy.bicep new file mode 100644 index 000000000..1c018d575 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/deploy.bicep @@ -0,0 +1,49 @@ +@description('Required. The name of the service bus namespace topic') +param name string + +@description('Required. The name of the parent service bus namespace') +param namespaceName string + +@description('Required. The name of the parent service bus namespace topic') +param topicName string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource topic 'topics@2021-06-01-preview' existing = { + name: topicName + } +} + +resource authorizationRule 'Microsoft.ServiceBus/namespaces/topics/authorizationRules@2021-06-01-preview' = { + name: name + parent: namespace::topic + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The Resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/readme.md new file mode 100644 index 000000000..d949fb650 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/readme.md @@ -0,0 +1,31 @@ +# ServiceBus Namespace Topic Authorization Rules `[Microsoft.ServiceBus/namespaces/topics/authorizationRules]` + +This module deploys an authorization rule for a service bus namespace topic. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/topics/authorizationRules` | 2021-06-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 | +| `name` | string | | | Required. The name of the service bus namespace topic | +| `namespaceName` | string | | | Required. The name of the parent service bus namespace | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | Optional. The rights associated with the rule. | +| `topicName` | string | | | Required. The name of the parent service bus namespace topic | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The Resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Topics/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics/authorizationRules) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/authorizationRules/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/deploy.bicep new file mode 100644 index 000000000..e16fbc08c --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/deploy.bicep @@ -0,0 +1,145 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Topic.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. Name of the Service Bus Topic.') +@minLength(6) +@maxLength(50) +param name string + +@description('Optional. The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. Default is 1024.') +param maxSizeInMegabytes int = 1024 + +@description('Optional. A value indicating if this topic requires duplicate detection.') +param requiresDuplicateDetection bool = false + +@description('Optional. ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself.') +param defaultMessageTimeToLive string = 'P14D' + +@description('Optional. Value that indicates whether server-side batched operations are enabled.') +param enableBatchedOperations bool = true + +@description('Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes.') +param duplicateDetectionHistoryTimeWindow string = 'PT10M' + +@description('Optional. Maximum size (in KB) of the message payload that can be accepted by the topic. This property is only used in Premium today and default is 1024.') +param maxMessageSizeInKilobytes int = 1024 + +@description('Optional. Value that indicates whether the topic supports ordering.') +param supportOrdering bool = false + +@description('Optional. ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes.') +param autoDeleteOnIdle string = 'PT5M' + +@description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown') +@allowed([ + 'Active' + 'Disabled' + 'Restoring' + 'SendDisabled' + 'ReceiveDisabled' + 'Creating' + 'Deleting' + 'Renaming' + 'Unknown' +]) +param status string = 'Active' + +@description('Optional. A value that indicates whether the topic is to be partitioned across multiple message brokers.') +param enablePartitioning bool = false + +@description('Optional. A value that indicates whether Express Entities are enabled. An express topic holds a message in memory temporarily before writing it to persistent storage.') +param enableExpress bool = false + +@description('Optional. Authorization Rules for the Service Bus Topic') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + } +] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource topic 'Microsoft.ServiceBus/namespaces/topics@2021-06-01-preview' = { + name: name + parent: namespace + properties: { + autoDeleteOnIdle: autoDeleteOnIdle + defaultMessageTimeToLive: defaultMessageTimeToLive + duplicateDetectionHistoryTimeWindow: duplicateDetectionHistoryTimeWindow + enableBatchedOperations: enableBatchedOperations + enableExpress: enableExpress + enablePartitioning: enablePartitioning + maxMessageSizeInKilobytes: maxMessageSizeInKilobytes + maxSizeInMegabytes: maxSizeInMegabytes + requiresDuplicateDetection: requiresDuplicateDetection + status: status + supportOrdering: supportOrdering + } +} + +module topic_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + topicName: topic.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +resource topic_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${topic.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: topic +} + +module topic_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: topic.id + } +}] + +@description('The name of the deployed topic') +output name string = topic.name + +@description('The resource ID of the deployed topic') +output resourceId string = topic.id + +@description('The resource group of the deployed topic') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/readme.md new file mode 100644 index 000000000..4034a43c6 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/readme.md @@ -0,0 +1,71 @@ +# ServiceBus Namespace Topic `[Microsoft.ServiceBus/namespaces/topics]` + +This module deploys a topic for a service bus namespace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ServiceBus/namespaces/topics` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/topics/authorizationRules` | 2021-06-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Optional. Authorization Rules for the Service Bus Topic | +| `autoDeleteOnIdle` | string | `PT5M` | | Optional. ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `defaultMessageTimeToLive` | string | `P14D` | | Optional. ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself. | +| `duplicateDetectionHistoryTimeWindow` | string | `PT10M` | | Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes. | +| `enableBatchedOperations` | bool | `True` | | Optional. Value that indicates whether server-side batched operations are enabled. | +| `enableExpress` | bool | | | Optional. A value that indicates whether Express Entities are enabled. An express topic holds a message in memory temporarily before writing it to persistent storage. | +| `enablePartitioning` | bool | | | Optional. A value that indicates whether the topic is to be partitioned across multiple message brokers. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `maxMessageSizeInKilobytes` | int | `1024` | | Optional. Maximum size (in KB) of the message payload that can be accepted by the topic. This property is only used in Premium today and default is 1024. | +| `maxSizeInMegabytes` | int | `1024` | | Optional. The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. Default is 1024. | +| `name` | string | | | Required. Name of the Service Bus Topic. | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Topic. | +| `requiresDuplicateDetection` | bool | | | Optional. A value indicating if this topic requires duplicate detection. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `status` | string | `Active` | `[Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown]` | Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown | +| `supportOrdering` | bool | | | Optional. Value that indicates whether the topic supports ordering. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed topic | +| `resourceGroupName` | string | The resource group of the deployed topic | +| `resourceId` | string | The resource ID of the deployed topic | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces/Topics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics) +- [Namespaces/Topics/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics/authorizationRules) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/topics/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/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/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/deploy.bicep b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/deploy.bicep new file mode 100644 index 000000000..1d45c326d --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/deploy.bicep @@ -0,0 +1,39 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the virtual network rule') +param name string = '${namespaceName}-vnr' + +@description('Required. Resource ID of Virtual Network Subnet') +param virtualNetworkSubnetId string + +@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 namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource virtualNetworkRule 'Microsoft.ServiceBus/namespaces/virtualNetworkRules@2018-01-01-preview' = { + name: name + parent: namespace + properties: { + virtualNetworkSubnetId: virtualNetworkSubnetId + } +} + +@description('The name of the virtual network rule.') +output name string = virtualNetworkRule.name + +@description('The Resource ID of the virtual network rule.') +output resourceId string = virtualNetworkRule.id + +@description('The name of the Resource Group the virtual network rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/readme.md b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/readme.md new file mode 100644 index 000000000..5a561f17b --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/readme.md @@ -0,0 +1,30 @@ +# ServiceBus Namespace Virtual Network Rules `[Microsoft.ServiceBus/namespaces/virtualNetworkRules]` + +This module deploys a virtual network rule for a service bus namespace. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/virtualnetworkrules` | 2018-01-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 | +| `name` | string | `[format('{0}-vnr', parameters('namespaceName'))]` | | Optional. The name of the virtual network rule | +| `namespaceName` | string | | | Required. Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `virtualNetworkSubnetId` | string | | | Required. Resource ID of Virtual Network Subnet | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network rule. | +| `resourceGroupName` | string | The name of the Resource Group the virtual network rule was created in. | +| `resourceId` | string | The Resource ID of the virtual network rule. | + +## Template references + +- [Namespaces/Virtualnetworkrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/virtualnetworkrules) diff --git a/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/version.json b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceBus/namespaces/virtualNetworkRules/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/carml/1.0.0/Microsoft.ServiceFabric/clusters/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..123939358 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = [for principalId in principalIds: { + name: guid(serviceFabricCluster.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: serviceFabricCluster +}] diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/cert.parameters.json b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/cert.parameters.json new file mode 100644 index 000000000..668b6d8d1 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/cert.parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sfc-cert-001" + }, + "managementEndpoint": { + "value": "https://<>-az-sfc-cert-001.westeurope.cloudapp.azure.com:19080" + }, + "reliabilityLevel": { + "value": "None" + }, + "certificate": { + "value": { + "thumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", // Mutual exclusive with the other cert specs + "x509StoreName": "My" + } + }, + "nodeTypes": { + "value": [ + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": 65534, + "startPort": 49152 + }, + "httpGatewayEndpointPort": 19080, + "isPrimary": true, + "name": "Node01" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/full.parameters.json b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/full.parameters.json new file mode 100644 index 000000000..6a7a61614 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/full.parameters.json @@ -0,0 +1,205 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sfc-full-001" + }, + "tags": { + "value": { + "resourceType": "Service Fabric", + "clusterName": "<>-az-sfc-full-001" + } + }, + "addOnFeatures": { + "value": [ + "RepairManager", + "DnsService", + "BackupRestoreService", + "ResourceMonitorService" + ] + }, + "maxUnusedVersionsToKeep": { + "value": 2 + }, + "azureActiveDirectory": { + "value": { + "clientApplication": "<>", + "clusterApplication": "cf33fea8-b30f-424f-ab73-c48d99e0b222", + "tenantId": "<>" + } + }, + "certificateCommonNames": { + "value": { + "commonNames": [ + { + "certificateCommonName": "certcommon", + "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130" + } + ], + "x509StoreName": "" + } + }, + "clientCertificateCommonNames": { + "value": [ + { + "certificateCommonName": "clientcommoncert1", + "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", + "isAdmin": false + }, + { + "certificateCommonName": "clientcommoncert2", + "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC131", + "isAdmin": false + } + ] + }, + "clientCertificateThumbprints": { + "value": [ + { + "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", + "isAdmin": false + }, + { + "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC131", + "isAdmin": false + } + ] + }, + "diagnosticsStorageAccountConfig": { + "value": { + "blobEndpoint": "https://adp<>azsaweux001.blob.core.windows.net/", + "protectedAccountKeyName": "StorageAccountKey1", + "queueEndpoint": "https://adp<>azsaweux001.queue.core.windows.net/", + "storageAccountName": "adp<>azsaweux001", + "tableEndpoint": "https://adp<>azsaweux001.table.core.windows.net/" + } + }, + "fabricSettings": { + "value": [ + { + "name": "Security", + "parameters": [ + { + "name": "ClusterProtectionLevel", + "value": "EncryptAndSign" + } + ] + }, + { + "name": "UpgradeService", + "parameters": [ + { + "name": "AppPollIntervalInSeconds", + "value": "60" + } + ] + } + ] + }, + "managementEndpoint": { + "value": "https://<>-az-sfc-full-001.westeurope.cloudapp.azure.com:19080" + }, + "nodeTypes": { + "value": [ + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "capacities": {}, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Silver", + "ephemeralPorts": { + "endPort": 65534, + "startPort": 49152 + }, + "httpGatewayEndpointPort": 19080, + "isPrimary": true, + "isStateless": false, + "multipleAvailabilityZones": false, + "name": "Node01", + "placementProperties": {}, + "reverseProxyEndpointPort": "", + "vmInstanceCount": 5 + }, + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": 64000, + "startPort": 49000 + }, + "httpGatewayEndpointPort": 19007, + "isPrimary": true, + "name": "Node02", + "vmInstanceCount": 5 + } + ] + }, + "notifications": { + "value": [ + { + "isEnabled": true, + "notificationCategory": "WaveProgress", + "notificationLevel": "Critical", + "notificationTargets": [ + { + "notificationChannel": "EmailUser", + "receivers": [ + "SomeReceiver" + ] + } + ] + } + ] + }, + "upgradeDescription": { + "value": { + "forceRestart": false, + "upgradeReplicaSetCheckTimeout": "1.00:00:00", + "healthCheckWaitDuration": "00:00:30", + "healthCheckStableDuration": "00:01:00", + "healthCheckRetryTimeout": "00:45:00", + "upgradeTimeout": "02:00:00", + "upgradeDomainTimeout": "02:00:00", + "healthPolicy": { + "maxPercentUnhealthyNodes": 0, + "maxPercentUnhealthyApplications": 0 + }, + "deltaHealthPolicy": { + "maxPercentDeltaUnhealthyNodes": 0, + "maxPercentUpgradeDomainDeltaUnhealthyNodes": 0, + "maxPercentDeltaUnhealthyApplications": 0 + } + } + }, + "reliabilityLevel": { + "value": "Silver" + }, + "vmImage": { + "value": "Linux" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "applicationTypes": { + "value": [ + { + "name": "WordCount" // not idempotent + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/min.parameters.json new file mode 100644 index 000000000..b7673a725 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/.parameters/min.parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sfc-min-001" + }, + "managementEndpoint": { + "value": "https://<>-az-sfc-min-001.westeurope.cloudapp.azure.com:19080" + }, + "reliabilityLevel": { + "value": "None" + }, + "nodeTypes": { + "value": [ + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": 65534, + "startPort": 49152 + }, + "httpGatewayEndpointPort": 19080, + "isPrimary": true, + "name": "Node01" + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/deploy.bicep b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/deploy.bicep new file mode 100644 index 000000000..dbc0d3b70 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/deploy.bicep @@ -0,0 +1,35 @@ +@description('Required. Name of the Service Fabric cluster.') +param serviceFabricClusterName string = '' + +@description('Optional. Application type name.') +param name string = 'defaultApplicationType' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@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 serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' existing = { + name: serviceFabricClusterName +} + +resource applicationTypes 'Microsoft.ServiceFabric/clusters/applicationTypes@2021-06-01' = { + name: name + parent: serviceFabricCluster + tags: tags +} + +@description('The resource name of the Application type.') +output name string = applicationTypes.name + +@description('The resource group of the Application type.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Application type.') +output resourceID string = applicationTypes.id diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/readme.md b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/readme.md new file mode 100644 index 000000000..796bec35e --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/readme.md @@ -0,0 +1,47 @@ +# ServiceFabric Cluster Application Type `[Microsoft.ServiceFabric/clusters/applicationTypes]` + +This module deploys a ServiceFabric cluster application type. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceFabric/clusters/applicationTypes` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `defaultApplicationType` | | Optional. Application type name. | +| `serviceFabricClusterName` | string | | | Required. Name of the Service Fabric cluster. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The resource name of the Application type. | +| `resourceGroupName` | string | The resource group of the Application type. | +| `resourceID` | string | The resource ID of the Application type. | + +## Template references + +- [Clusters/Applicationtypes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceFabric/2021-06-01/clusters/applicationTypes) diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/version.json b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/applicationTypes/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/carml/1.0.0/Microsoft.ServiceFabric/clusters/deploy.bicep b/carml/1.0.0/Microsoft.ServiceFabric/clusters/deploy.bicep new file mode 100644 index 000000000..affb81075 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/deploy.bicep @@ -0,0 +1,313 @@ +@description('Required. Name of the Service Fabric cluster.') +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@allowed([ + 'BackupRestoreService' + 'DnsService' + 'RepairManager' + 'ResourceMonitorService' +]) +@description('Optional. The list of add-on features to enable in the cluster.') +param addOnFeatures array = [] + +@description('Required. Number of unused versions per application type to keep.') +param maxUnusedVersionsToKeep int = 3 + +@description('Optional. The settings to enable AAD authentication on the cluster.') +param azureActiveDirectory object = {} + +@description('Optional. Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location') +param certificate object = {} + +@description('Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster.') +param certificateCommonNames object = {} + +@description('Optional. The list of client certificates referenced by common name that are allowed to manage the cluster.') +param clientCertificateCommonNames array = [] + +@description('Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster.') +param clientCertificateThumbprints array = [] + +@description('Optional. The Service Fabric runtime version of the cluster. This property can only by set the user when upgradeMode is set to "Manual". To get list of available Service Fabric versions for new clusters use ClusterVersion API. To get the list of available version for existing clusters use availableClusterVersions.') +param clusterCodeVersion string = '' + +@description('Optional. The storage account information for storing Service Fabric diagnostic logs.') +param diagnosticsStorageAccountConfig object = {} + +@description('Optional. Indicates if the event store service is enabled.') +param eventStoreServiceEnabled bool = false + +@description('Optional. The list of custom fabric settings to configure the cluster.') +param fabricSettings array = [] + +@description('Optional. Indicates if infrastructure service manager is enabled.') +param infrastructureServiceManager bool = false + +@description('Required. The http management endpoint of the cluster.') +param managementEndpoint string + +@description('Required. The list of node types in the cluster.') +param nodeTypes array = [] + +@description('Optional. Indicates a list of notification channels for cluster events.') +param notifications array = [] + +@allowed([ + 'Bronze' + 'Gold' + 'None' + 'Platinum' + 'Silver' +]) +@description('Optional. The reliability level sets the replica set size of system services. Learn about ReliabilityLevel (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-capacity). - None - Run the System services with a target replica set count of 1. This should only be used for test clusters. - Bronze - Run the System services with a target replica set count of 3. This should only be used for test clusters. - Silver - Run the System services with a target replica set count of 5. - Gold - Run the System services with a target replica set count of 7. - Platinum - Run the System services with a target replica set count of 9.') +param reliabilityLevel string + +@description('Optional. Describes the certificate details.') +param reverseProxyCertificate object = {} + +@description('Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster.') +param reverseProxyCertificateCommonNames object = {} + +@allowed([ + 'Hierarchical' + 'Parallel' +]) +@description('Optional. This property controls the logical grouping of VMs in upgrade domains (UDs). This property cannot be modified if a node type with multiple Availability Zones is already present in the cluster.') +param sfZonalUpgradeMode string = 'Hierarchical' + +@description('Optional. Describes the policy used when upgrading the cluster.') +param upgradeDescription object = {} + +@allowed([ + 'Automatic' + 'Manual' +]) +@description('Optional. The upgrade mode of the cluster when new Service Fabric runtime version is available.') +param upgradeMode string = 'Automatic' + +@description('Optional. Indicates the end date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC).') +param upgradePauseEndTimestampUtc string = '' + +@description('Optional. Indicates the start date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC).') +param upgradePauseStartTimestampUtc string = '' + +@allowed([ + 'Wave0' + 'Wave1' + 'Wave2' +]) +@description('Optional. Indicates when new cluster runtime version upgrades will be applied after they are released. By default is Wave0.') +param upgradeWave string = 'Wave0' + +@description('Optional. The VM image VMSS has been configured with. Generic names such as Windows or Linux can be used') +param vmImage string = '' + +@allowed([ + 'Hierarchical' + 'Parallel' +]) +@description('Optional. This property defines the upgrade mode for the virtual machine scale set, it is mandatory if a node type with multiple Availability Zones is added.') +param vmssZonalUpgradeMode string = 'Hierarchical' + +@description('Optional. Boolean to pause automatic runtime version upgrades to the cluster.') +param waveUpgradePaused bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Array of Service Fabric cluster application types.') +param applicationTypes array = [] + +var clientCertificateCommonNames_var = [for clientCertificateCommonName in clientCertificateCommonNames: { + certificateCommonName: contains(clientCertificateCommonName, 'certificateCommonName') ? clientCertificateCommonName.certificateCommonName : null + certificateIssuerThumbprint: contains(clientCertificateCommonName, 'certificateIssuerThumbprint') ? clientCertificateCommonName.certificateIssuerThumbprint : null + isAdmin: contains(clientCertificateCommonName, 'isAdmin') ? clientCertificateCommonName.isAdmin : false +}] + +var clientCertificateThumbprints_var = [for clientCertificateThumbprint in clientCertificateThumbprints: { + certificateThumbprint: contains(clientCertificateThumbprint, 'certificateThumbprint') ? clientCertificateThumbprint.certificateThumbprint : null + isAdmin: contains(clientCertificateThumbprint, 'isAdmin') ? clientCertificateThumbprint.isAdmin : false +}] + +var fabricSettings_var = [for fabricSetting in fabricSettings: { + name: contains(fabricSetting, 'name') ? fabricSetting.name : null + parameters: contains(fabricSetting, 'parameters') ? fabricSetting.parameters : null +}] + +var nodeTypes_var = [for nodeType in nodeTypes: { + applicationPorts: contains(nodeType, 'applicationPorts') ? { + endPort: contains(nodeType.applicationPorts, 'endPort') ? nodeType.applicationPorts.endPort : null + startPort: contains(nodeType.applicationPorts, 'startPort') ? nodeType.applicationPorts.startPort : null + } : null + capacities: contains(nodeType, 'capacities') ? nodeType.capacities : null + clientConnectionEndpointPort: contains(nodeType, 'clientConnectionEndpointPort') ? nodeType.clientConnectionEndpointPort : null + durabilityLevel: contains(nodeType, 'durabilityLevel') ? nodeType.durabilityLevel : null + ephemeralPorts: contains(nodeType, 'ephemeralPorts') ? { + endPort: contains(nodeType.ephemeralPorts, 'endPort') ? nodeType.ephemeralPorts.endPort : null + startPort: contains(nodeType.ephemeralPorts, 'startPort') ? nodeType.ephemeralPorts.startPort : null + } : null + httpGatewayEndpointPort: contains(nodeType, 'httpGatewayEndpointPort') ? nodeType.httpGatewayEndpointPort : null + isPrimary: contains(nodeType, 'isPrimary') ? nodeType.isPrimary : null + isStateless: contains(nodeType, 'isStateless') ? nodeType.isStateless : null + multipleAvailabilityZones: contains(nodeType, 'multipleAvailabilityZones') ? nodeType.multipleAvailabilityZones : null + name: contains(nodeType, 'name') ? nodeType.name : 'Node00' + placementProperties: contains(nodeType, 'placementProperties') ? nodeType.placementProperties : null + reverseProxyEndpointPort: contains(nodeType, 'reverseProxyEndpointPort') ? nodeType.reverseProxyEndpointPort : null + vmInstanceCount: contains(nodeType, 'vmInstanceCount') ? nodeType.vmInstanceCount : 1 +}] + +var notifications_var = [for notification in notifications: { + isEnabled: contains(notification, 'isEnabled') ? notification.isEnabled : false + notificationCategory: contains(notification, 'notificationCategory') ? notification.notificationCategory : 'WaveProgress' + notificationLevel: contains(notification, 'notificationLevel') ? notification.notificationLevel : 'All' + notificationTargets: contains(notification, 'notificationTargets') ? notification.notificationTargets : [] +}] + +var upgradeDescription_var = union({ + deltaHealthPolicy: { + applicationDeltaHealthPolicies: contains(upgradeDescription, 'applicationDeltaHealthPolicies') ? upgradeDescription.applicationDeltaHealthPolicies : {} + maxPercentDeltaUnhealthyApplications: contains(upgradeDescription, 'maxPercentDeltaUnhealthyApplications') ? upgradeDescription.maxPercentDeltaUnhealthyApplications : 0 + maxPercentDeltaUnhealthyNodes: contains(upgradeDescription, 'maxPercentDeltaUnhealthyNodes') ? upgradeDescription.maxPercentDeltaUnhealthyNodes : 0 + maxPercentUpgradeDomainDeltaUnhealthyNodes: contains(upgradeDescription, 'maxPercentUpgradeDomainDeltaUnhealthyNodes') ? upgradeDescription.maxPercentUpgradeDomainDeltaUnhealthyNodes : 0 + } + forceRestart: contains(upgradeDescription, 'forceRestart') ? upgradeDescription.forceRestart : false + healthCheckRetryTimeout: contains(upgradeDescription, 'healthCheckRetryTimeout') ? upgradeDescription.healthCheckRetryTimeout : '00:45:00' + healthCheckStableDuration: contains(upgradeDescription, 'healthCheckStableDuration') ? upgradeDescription.healthCheckStableDuration : '00:01:00' + healthCheckWaitDuration: contains(upgradeDescription, 'healthCheckWaitDuration') ? upgradeDescription.healthCheckWaitDuration : '00:00:30' + upgradeDomainTimeout: contains(upgradeDescription, 'upgradeDomainTimeout') ? upgradeDescription.upgradeDomainTimeout : '02:00:00' + upgradeReplicaSetCheckTimeout: contains(upgradeDescription, 'upgradeReplicaSetCheckTimeout') ? upgradeDescription.upgradeReplicaSetCheckTimeout : '1.00:00:00' + upgradeTimeout: contains(upgradeDescription, 'upgradeTimeout') ? upgradeDescription.upgradeTimeout : '02:00:00' +}, contains(upgradeDescription, 'healthPolicy') ? { + healthPolicy: { + applicationHealthPolicies: contains(upgradeDescription.healthPolicy, 'applicationHealthPolicies') ? upgradeDescription.healthPolicy.applicationHealthPolicies : {} + maxPercentUnhealthyApplications: contains(upgradeDescription.healthPolicy, 'maxPercentUnhealthyApplications') ? upgradeDescription.healthPolicy.maxPercentUnhealthyApplications : 0 + maxPercentUnhealthyNodes: contains(upgradeDescription.healthPolicy, 'maxPercentUnhealthyNodes') ? upgradeDescription.healthPolicy.maxPercentUnhealthyNodes : 0 + } +} : {}) + +module pid_cuaId './.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +// Service Fabric cluster resource +resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' = { + name: name + location: location + tags: tags + properties: { + addOnFeatures: addOnFeatures + applicationTypeVersionsCleanupPolicy: { + maxUnusedVersionsToKeep: maxUnusedVersionsToKeep + } + azureActiveDirectory: !empty(azureActiveDirectory) ? { + clientApplication: contains(azureActiveDirectory, 'clientApplication') ? azureActiveDirectory.clientApplication : null + clusterApplication: contains(azureActiveDirectory, 'clusterApplication') ? azureActiveDirectory.clusterApplication : null + tenantId: contains(azureActiveDirectory, 'tenantId') ? azureActiveDirectory.tenantId : null + } : null + certificate: !empty(certificate) ? { + thumbprint: contains(certificate, 'thumbprint') ? certificate.thumbprint : null + thumbprintSecondary: contains(certificate, 'thumbprintSecondary') ? certificate.thumbprintSecondary : null + x509StoreName: contains(certificate, 'x509StoreName') ? certificate.x509StoreName : null + } : null + certificateCommonNames: !empty(certificateCommonNames) ? { + commonNames: contains(certificateCommonNames, 'commonNames') ? certificateCommonNames.commonNames : null + x509StoreName: contains(certificateCommonNames, 'certificateCommonNamesx509StoreName') ? certificateCommonNames.certificateCommonNamesx509StoreName : null + } : null + clientCertificateCommonNames: !empty(clientCertificateCommonNames) ? clientCertificateCommonNames_var : null + clientCertificateThumbprints: !empty(clientCertificateThumbprints) ? clientCertificateThumbprints_var : null + clusterCodeVersion: !empty(clusterCodeVersion) ? clusterCodeVersion : null + diagnosticsStorageAccountConfig: !empty(diagnosticsStorageAccountConfig) ? { + blobEndpoint: contains(diagnosticsStorageAccountConfig, 'blobEndpoint') ? diagnosticsStorageAccountConfig.blobEndpoint : null + protectedAccountKeyName: contains(diagnosticsStorageAccountConfig, 'protectedAccountKeyName') ? diagnosticsStorageAccountConfig.protectedAccountKeyName : null + protectedAccountKeyName2: contains(diagnosticsStorageAccountConfig, 'protectedAccountKeyName2') ? diagnosticsStorageAccountConfig.protectedAccountKeyName2 : null + queueEndpoint: contains(diagnosticsStorageAccountConfig, 'queueEndpoint') ? diagnosticsStorageAccountConfig.queueEndpoint : null + storageAccountName: contains(diagnosticsStorageAccountConfig, 'storageAccountName') ? diagnosticsStorageAccountConfig.storageAccountName : null + tableEndpoint: contains(diagnosticsStorageAccountConfig, 'tableEndpoint') ? diagnosticsStorageAccountConfig.tableEndpoint : null + } : null + eventStoreServiceEnabled: eventStoreServiceEnabled + fabricSettings: !empty(fabricSettings) ? fabricSettings_var : null + infrastructureServiceManager: infrastructureServiceManager + managementEndpoint: managementEndpoint + nodeTypes: !empty(nodeTypes) ? nodeTypes_var : [] + notifications: !empty(notifications) ? notifications_var : null + reliabilityLevel: !empty(reliabilityLevel) ? reliabilityLevel : 'None' + reverseProxyCertificate: !empty(reverseProxyCertificate) ? { + thumbprint: contains(reverseProxyCertificate, 'thumbprint') ? reverseProxyCertificate.thumbprint : null + thumbprintSecondary: contains(reverseProxyCertificate, 'thumbprintSecondary') ? reverseProxyCertificate.thumbprintSecondary : null + x509StoreName: contains(reverseProxyCertificate, 'x509StoreName') ? reverseProxyCertificate.x509StoreName : null + } : null + reverseProxyCertificateCommonNames: !empty(reverseProxyCertificateCommonNames) ? { + commonNames: contains(reverseProxyCertificateCommonNames, 'commonNames') ? reverseProxyCertificateCommonNames.commonNames : null + x509StoreName: contains(reverseProxyCertificateCommonNames, 'x509StoreName') ? reverseProxyCertificateCommonNames.x509StoreName : null + } : null + sfZonalUpgradeMode: !empty(sfZonalUpgradeMode) ? sfZonalUpgradeMode : null + upgradeDescription: !empty(upgradeDescription) ? upgradeDescription_var : null + upgradeMode: !empty(upgradeMode) ? upgradeMode : null + upgradePauseEndTimestampUtc: !empty(upgradePauseEndTimestampUtc) ? upgradePauseEndTimestampUtc : null + upgradePauseStartTimestampUtc: !empty(upgradePauseStartTimestampUtc) ? upgradePauseStartTimestampUtc : null + upgradeWave: !empty(upgradeWave) ? upgradeWave : null + vmImage: !empty(vmImage) ? vmImage : null + vmssZonalUpgradeMode: !empty(vmssZonalUpgradeMode) ? vmssZonalUpgradeMode : null + waveUpgradePaused: waveUpgradePaused + } +} + +// Service Fabric cluster resource lock +resource serviceFabricCluster_lock 'Microsoft.Authorization/locks@2016-09-01' = if (lock != 'NotSpecified') { + name: '${serviceFabricCluster.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: serviceFabricCluster +} + +// Service Fabric cluster RBAC assignment +module serviceFabricCluster_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ServiceFabric-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: serviceFabricCluster.id + } +}] + +// Service Fabric cluster application types +module serviceFabricCluster_applicationTypes 'applicationTypes/deploy.bicep' = [for applicationType in applicationTypes: { + name: '${uniqueString(deployment().name, location)}-SFC-${applicationType.name}' + params: { + name: applicationType.name + serviceFabricClusterName: serviceFabricCluster.name + tags: contains(applicationType, 'tags') ? applicationType.tags : {} + } +}] + +@description('The Service Fabric Cluster name.') +output name string = serviceFabricCluster.name + +@description('The Service Fabric Cluster resource group.') +output resourceGroupName string = resourceGroup().name + +@description('The Service Fabric Cluster resource ID.') +output resourceId string = serviceFabricCluster.id + +@description('The Service Fabric Cluster endpoint.') +output endpoint string = serviceFabricCluster.properties.clusterEndpoint diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/readme.md b/carml/1.0.0/Microsoft.ServiceFabric/clusters/readme.md new file mode 100644 index 000000000..e42c19b19 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/readme.md @@ -0,0 +1,128 @@ +# ServiceFabric Cluster `[Microsoft.ServiceFabric/clusters]` + +This module deploys a service fabric cluster. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2016-09-01 | +| `Microsoft.Authorization/roleAssignments` | 2020-04-01-preview | +| `Microsoft.ServiceFabric/clusters` | 2021-06-01 | +| `Microsoft.ServiceFabric/clusters/applicationTypes` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addOnFeatures` | array | `[]` | `[BackupRestoreService, DnsService, RepairManager, ResourceMonitorService]` | Optional. The list of add-on features to enable in the cluster. | +| `applicationTypes` | _[applicationTypes](applicationTypes/readme.md)_ array | `[]` | | Optional. Array of Service Fabric cluster application types. | +| `azureActiveDirectory` | object | `{object}` | | Optional. The settings to enable AAD authentication on the cluster. | +| `certificate` | object | `{object}` | | Optional. Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location | +| `certificateCommonNames` | object | `{object}` | | Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster. | +| `clientCertificateCommonNames` | array | `[]` | | Optional. The list of client certificates referenced by common name that are allowed to manage the cluster. | +| `clientCertificateThumbprints` | array | `[]` | | Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster. | +| `clusterCodeVersion` | string | | | Optional. The Service Fabric runtime version of the cluster. This property can only by set the user when upgradeMode is set to "Manual". To get list of available Service Fabric versions for new clusters use ClusterVersion API. To get the list of available version for existing clusters use availableClusterVersions. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticsStorageAccountConfig` | object | `{object}` | | Optional. The storage account information for storing Service Fabric diagnostic logs. | +| `eventStoreServiceEnabled` | bool | | | Optional. Indicates if the event store service is enabled. | +| `fabricSettings` | array | `[]` | | Optional. The list of custom fabric settings to configure the cluster. | +| `infrastructureServiceManager` | bool | | | Optional. Indicates if infrastructure service manager is enabled. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `managementEndpoint` | string | | | Required. The http management endpoint of the cluster. | +| `maxUnusedVersionsToKeep` | int | `3` | | Required. Number of unused versions per application type to keep. | +| `name` | string | | | Required. Name of the Service Fabric cluster. | +| `nodeTypes` | array | `[]` | | Required. The list of node types in the cluster. | +| `notifications` | array | `[]` | | Optional. Indicates a list of notification channels for cluster events. | +| `reliabilityLevel` | string | | `[Bronze, Gold, None, Platinum, Silver]` | Optional. The reliability level sets the replica set size of system services. Learn about ReliabilityLevel (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-capacity). - None - Run the System services with a target replica set count of 1. This should only be used for test clusters. - Bronze - Run the System services with a target replica set count of 3. This should only be used for test clusters. - Silver - Run the System services with a target replica set count of 5. - Gold - Run the System services with a target replica set count of 7. - Platinum - Run the System services with a target replica set count of 9. | +| `reverseProxyCertificate` | object | `{object}` | | Optional. Describes the certificate details. | +| `reverseProxyCertificateCommonNames` | object | `{object}` | | Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sfZonalUpgradeMode` | string | `Hierarchical` | `[Hierarchical, Parallel]` | Optional. This property controls the logical grouping of VMs in upgrade domains (UDs). This property cannot be modified if a node type with multiple Availability Zones is already present in the cluster. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `upgradeDescription` | object | `{object}` | | Optional. Describes the policy used when upgrading the cluster. | +| `upgradeMode` | string | `Automatic` | `[Automatic, Manual]` | Optional. The upgrade mode of the cluster when new Service Fabric runtime version is available. | +| `upgradePauseEndTimestampUtc` | string | | | Optional. Indicates the end date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC). | +| `upgradePauseStartTimestampUtc` | string | | | Optional. Indicates the start date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC). | +| `upgradeWave` | string | `Wave0` | `[Wave0, Wave1, Wave2]` | Optional. Indicates when new cluster runtime version upgrades will be applied after they are released. By default is Wave0. | +| `vmImage` | string | | | Optional. The VM image VMSS has been configured with. Generic names such as Windows or Linux can be used | +| `vmssZonalUpgradeMode` | string | `Hierarchical` | `[Hierarchical, Parallel]` | Optional. This property defines the upgrade mode for the virtual machine scale set, it is mandatory if a node type with multiple Availability Zones is added. | +| `waveUpgradePaused` | bool | | | Optional. Boolean to pause automatic runtime version upgrades to the cluster. | + +### Parameter Usage: `notifications` + +```json +"notifications": { + "value": [ + { + "isEnabled": true, // Required. Indicates if the notification is enabled. + "notificationCategory": "WaveProgress", // Required. The category of notification. Possible values include: "WaveProgress". + "notificationLevel": "Critical", // Required. The level of notification. Possible values include: "Critical", "All". + "notificationTargets": [ + { + "notificationChannel": "EmailUser", // Required. The notification channel indicates the type of receivers subscribed to the notification, either user or subscription. Possible values include: "EmailUser", "EmailSubscription". + "receivers": [ + "SomeReceiver" // Required. List of targets that subscribe to the notification. + ] + } + ] + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `endpoint` | string | The Service Fabric Cluster endpoint. | +| `name` | string | The Service Fabric Cluster name. | +| `resourceGroupName` | string | The Service Fabric Cluster resource group. | +| `resourceId` | string | The Service Fabric Cluster resource ID. | + +## Template references + +- [Clusters](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceFabric/2021-06-01/clusters) +- [Clusters/Applicationtypes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceFabric/2021-06-01/clusters/applicationTypes) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2016-09-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-04-01-preview/roleAssignments) diff --git a/carml/1.0.0/Microsoft.ServiceFabric/clusters/version.json b/carml/1.0.0/Microsoft.ServiceFabric/clusters/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.ServiceFabric/clusters/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/carml/1.0.0/Microsoft.Sql/managedInstances/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..a6285d10d --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/.bicep/nested_rbac.bicep @@ -0,0 +1,35 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2020-08-01-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(managedInstance.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: managedInstance +}] diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/.parameters/parameters.json b/carml/1.0.0/Microsoft.Sql/managedInstances/.parameters/parameters.json new file mode 100644 index 000000000..75f38b339 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/.parameters/parameters.json @@ -0,0 +1,144 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sqlmi-x-002" + }, + "administratorLogin": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLogin" + } + }, + "administratorLoginPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLoginPassword" + } + }, + "subnetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-sqlmi/subnets/<>-az-subnet-x-sqlmi" + }, + "skuName": { + "value": "GP_Gen5" + }, + "skuTier": { + "value": "GeneralPurpose" + }, + "storageSizeInGB": { + "value": 32 + }, + "vCores": { + "value": 4 + }, + "licenseType": { + "value": "LicenseIncluded" + }, + "hardwareFamily": { + "value": "Gen5" + }, + "dnsZonePartner": { + "value": "" + }, + "timezoneId": { + "value": "UTC" + }, + "collation": { + "value": "SQL_Latin1_General_CP1_CI_AS" + }, + "proxyOverride": { + "value": "Proxy" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "primaryUserAssignedIdentityId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001" + }, + "publicDataEndpointEnabled": { + "value": false + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "keys": { + "value": [ + { + "name": "adp-<>-az-kv-x-sqlmi_keyEncryptionKeySqlMi_4bf367f64c914d8ba698700fb598ad07", // ID must be updated for new keys + "uri": "https://adp-<>-az-kv-x-sqlmi.vault.azure.net/keys/keyEncryptionKeySqlMi/4bf367f64c914d8ba698700fb598ad07", // ID must be updated for new keys + "serverKeyType": "AzureKeyVault" + } + ] + }, + "encryptionProtectorObj": { + "value": { + "serverKeyName": "adp-<>-az-kv-x-sqlmi_keyEncryptionKeySqlMi_4bf367f64c914d8ba698700fb598ad07", // ID must be updated for new keys + "serverKeyType": "AzureKeyVault" + } + }, + "securityAlertPoliciesObj": { + "value": { + "name": "default", + "state": "Enabled", + "emailAccountAdmins": true + } + }, + "vulnerabilityAssessmentsObj": { + "value": { + "name": "default", + "emailSubscriptionAdmins": true, + "recurringScansIsEnabled": true, + "recurringScansEmails": [ + "test1@contoso.com", + "test2@contoso.com" + ], + "vulnerabilityAssessmentsStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + }, + "databases": { + "value": [ + { + "name": "<>-az-sqlmidb-x-001", + "backupShortTermRetentionPolicies": { + "name": "default" + }, + "backupLongTermRetentionPolicies": { + "name": "default" + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/deploy.bicep new file mode 100644 index 000000000..abb6be4a2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/deploy.bicep @@ -0,0 +1,46 @@ +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Required. Login name of the managed instance administrator.') +param login string + +@description('Required. SID (object ID) of the managed instance administrator.') +param sid string + +@description('Optional. The name of the managed instance administrator') +param name string = 'ActiveDirectory' + +@description('Optional. Tenant ID of the managed instance administrator.') +param tenantId string = '' + +@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 managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource administrator 'Microsoft.Sql/managedInstances/administrators@2021-02-01-preview' = { + name: name + parent: managedInstance + properties: { + administratorType: 'ActiveDirectory' + login: login + sid: sid + tenantId: tenantId + } +} + +@description('The name of the deployed managed instance') +output name string = administrator.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = administrator.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/readme.md new file mode 100644 index 000000000..af24ba2f4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/readme.md @@ -0,0 +1,32 @@ +# SQL Managed Instances Administrator `[Microsoft.Sql/managedInstances/administrators]` + +This module deploys an administrator for the SQL managed instance + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/administrators` | 2021-02-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 | +| `login` | string | | | Required. Login name of the managed instance administrator. | +| `managedInstanceName` | string | | | Required. Name of the SQL managed instance. | +| `name` | string | `ActiveDirectory` | | Optional. The name of the managed instance administrator | +| `sid` | string | | | Required. SID (object ID) of the managed instance administrator. | +| `tenantId` | string | | | Optional. Tenant ID of the managed instance administrator. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | + +## Template references + +- [Managedinstances/Administrators](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/administrators) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/administrators/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/carml/1.0.0/Microsoft.Sql/managedInstances/databases/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/deploy.bicep new file mode 100644 index 000000000..b7065f2cb --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. The name of the Long Term Retention backup policy. For example "default".') +param name string + +@description('Required. The name of the managed instance database') +param databaseName string + +@description('Required. Name of the managed instance.') +param managedInstanceName string + +@description('Optional. The week of year to take the yearly backup in an ISO 8601 format.') +param weekOfYear int = 5 + +@description('Optional. The weekly retention policy for an LTR backup in an ISO 8601 format.') +param weeklyRetention string = 'P1M' + +@description('Optional. The monthly retention policy for an LTR backup in an ISO 8601 format.') +param monthlyRetention string = 'P1Y' + +@description('Optional. The yearly retention policy for an LTR backup in an ISO 8601 format.') +param yearlyRetention string = 'P5Y' + +@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 managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName + + resource managedInstaceDatabase 'databases@2020-02-02-preview' existing = { + name: databaseName + } +} + +resource backupLongTermRetentionPolicy 'Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies@2021-02-01-preview' = { + name: name + parent: managedInstance::managedInstaceDatabase + properties: { + monthlyRetention: monthlyRetention + weeklyRetention: weeklyRetention + weekOfYear: weekOfYear + yearlyRetention: yearlyRetention + } +} + +@description('The name of the deployed database backup long-term retention policy') +output name string = backupLongTermRetentionPolicy.name + +@description('The resource ID of the deployed database backup long-term retention policy') +output resourceId string = backupLongTermRetentionPolicy.id + +@description('The resource group of the deployed database backup long-term retention policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/readme.md new file mode 100644 index 000000000..be4a6eb1f --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/readme.md @@ -0,0 +1,34 @@ +# SQL Managed Instance Database Backup Long-Term Retention Policy `[Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies]` + +This module deploys a backup long-term retention policies for SQL Managed Instance databases + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies` | 2021-02-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 | +| `databaseName` | string | | | Required. The name of the managed instance database | +| `managedInstanceName` | string | | | Required. Name of the managed instance. | +| `monthlyRetention` | string | `P1Y` | | Optional. The monthly retention policy for an LTR backup in an ISO 8601 format. | +| `name` | string | | | Required. The name of the Long Term Retention backup policy. For example "default". | +| `weeklyRetention` | string | `P1M` | | Optional. The weekly retention policy for an LTR backup in an ISO 8601 format. | +| `weekOfYear` | int | `5` | | Optional. The week of year to take the yearly backup in an ISO 8601 format. | +| `yearlyRetention` | string | `P5Y` | | Optional. The yearly retention policy for an LTR backup in an ISO 8601 format. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database backup long-term retention policy | +| `resourceGroupName` | string | The resource group of the deployed database backup long-term retention policy | +| `resourceId` | string | The resource ID of the deployed database backup long-term retention policy | + +## Template references + +- [Managedinstances/Databases/Backuplongtermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/databases/backupLongTermRetentionPolicies) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/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/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/deploy.bicep new file mode 100644 index 000000000..bafa3edcb --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/deploy.bicep @@ -0,0 +1,44 @@ +@description('Required. The name of the Short Term Retention backup policy. For example "default".') +param name string + +@description('Required. The name of the SQL managed instance database') +param databaseName string + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. The backup retention period in days. This is how many days Point-in-Time Restore will be supported.') +param retentionDays int = 35 + +@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 managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName + + resource managedInstaceDatabase 'databases@2020-02-02-preview' existing = { + name: databaseName + } +} + +resource backupShortTermRetentionPolicy 'Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies@2017-03-01-preview' = { + name: name + parent: managedInstance::managedInstaceDatabase + properties: { + retentionDays: retentionDays + } +} + +@description('The name of the deployed database backup short-term retention policy') +output name string = backupShortTermRetentionPolicy.name + +@description('The resource ID of the deployed database backup short-term retention policy') +output resourceId string = backupShortTermRetentionPolicy.id + +@description('The resource group of the deployed database backup short-term retention policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/readme.md new file mode 100644 index 000000000..7f499715a --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/readme.md @@ -0,0 +1,32 @@ +# SQL Managed Instance Database Backup Short-Term Retention Policy `[Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies]` + +This module deploys a backup short-term retention policies for SQL Managed Instance databases + + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies` | 2017-03-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 | +| `databaseName` | string | | | Required. The name of the SQL managed instance database | +| `managedInstanceName` | string | | | Required. Name of the SQL managed instance. | +| `name` | string | | | Required. The name of the Short Term Retention backup policy. For example "default". | +| `retentionDays` | int | `35` | | Optional. The backup retention period in days. This is how many days Point-in-Time Restore will be supported. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database backup short-term retention policy | +| `resourceGroupName` | string | The resource group of the deployed database backup short-term retention policy | +| `resourceId` | string | The resource ID of the deployed database backup short-term retention policy | + +## Template references + +- [Managedinstances/Databases/Backupshorttermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/databases/backupShortTermRetentionPolicies) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/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/carml/1.0.0/Microsoft.Sql/managedInstances/databases/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/deploy.bicep new file mode 100644 index 000000000..a8bc1ddfe --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/deploy.bicep @@ -0,0 +1,186 @@ +@description('Required. The name of the SQL managed instance database.') +param name string + +@description('Required. The name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Collation of the managed instance database.') +param collation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. Conditional. If createMode is PointInTimeRestore, this value is required. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database.') +param restorePointInTime string = '' + +@description('Optional. Collation of the managed instance.') +param catalogCollation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. Managed database create mode. PointInTimeRestore: Create a database by restoring a point in time backup of an existing database. SourceDatabaseName, SourceManagedInstanceName and PointInTime must be specified. RestoreExternalBackup: Create a database by restoring from external backup files. Collation, StorageContainerUri and StorageContainerSasToken must be specified. Recovery: Creates a database by restoring a geo-replicated backup. RecoverableDatabaseId must be specified as the recoverable database resource ID to restore.') +@allowed([ + 'Default' + 'RestoreExternalBackup' + 'PointInTimeRestore' + 'Recovery' + 'RestoreLongTermRetentionBackup' +]) +param createMode string = 'Default' + +@description('Optional. Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the uri of the storage container where backups for this restore are stored.') +param storageContainerUri string = '' + +@description('Optional. Conditional. The resource identifier of the source database associated with create operation of this database.') +param sourceDatabaseId string = '' + +@description('Optional. Conditional. The restorable dropped database resource ID to restore when creating this database.') +param restorableDroppedDatabaseId string = '' + +@description('Optional. Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the storage container sas token.') +param storageContainerSasToken string = '' + +@description('Optional. Conditional. The resource identifier of the recoverable database associated with create operation of this database.') +param recoverableDatabaseId string = '' + +@description('Optional. Conditional. The name of the Long Term Retention backup to be used for restore of this managed database.') +param longTermRetentionBackupResourceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. The configuration for the backup short term retention policy definition') +param backupShortTermRetentionPoliciesObj object = {} + +@description('Optional. The configuration for the backup long term retention policy definition') +param backupLongTermRetentionPoliciesObj object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'SQLInsights' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' +]) +param logsToEnable array = [ + 'SQLInsights' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource database 'Microsoft.Sql/managedInstances/databases@2021-05-01-preview' = { + name: name + parent: managedInstance + location: location + tags: tags + properties: { + collation: empty(collation) ? null : collation + restorePointInTime: empty(restorePointInTime) ? null : restorePointInTime + catalogCollation: empty(catalogCollation) ? null : catalogCollation + createMode: empty(createMode) ? null : createMode + storageContainerUri: empty(storageContainerUri) ? null : storageContainerUri + sourceDatabaseId: empty(sourceDatabaseId) ? null : sourceDatabaseId + restorableDroppedDatabaseId: empty(restorableDroppedDatabaseId) ? null : restorableDroppedDatabaseId + storageContainerSasToken: empty(storageContainerSasToken) ? null : storageContainerSasToken + recoverableDatabaseId: empty(recoverableDatabaseId) ? null : recoverableDatabaseId + longTermRetentionBackupResourceId: empty(longTermRetentionBackupResourceId) ? null : longTermRetentionBackupResourceId + } +} + +resource database_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${last(split(database.name, '/'))}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: database +} + +resource database_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${last(split(database.name, '/'))}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: database +} + +module database_backupShortTermRetentionPolicy 'backupShortTermRetentionPolicies/deploy.bicep' = if (!empty(backupShortTermRetentionPoliciesObj)) { + name: '${deployment().name}-BackupShortTRetPol' + params: { + managedInstanceName: managedInstanceName + databaseName: last(split(database.name, '/')) + name: backupShortTermRetentionPoliciesObj.name + retentionDays: contains(backupShortTermRetentionPoliciesObj, 'retentionDays') ? backupShortTermRetentionPoliciesObj.retentionDays : 35 + } +} + +module database_backupLongTermRetentionPolicy 'backupLongTermRetentionPolicies/deploy.bicep' = if (!empty(backupLongTermRetentionPoliciesObj)) { + name: '${deployment().name}-BackupLongTRetPol' + params: { + managedInstanceName: managedInstanceName + databaseName: last(split(database.name, '/')) + name: backupLongTermRetentionPoliciesObj.name + weekOfYear: contains(backupLongTermRetentionPoliciesObj, 'weekOfYear') ? backupLongTermRetentionPoliciesObj.weekOfYear : 5 + weeklyRetention: contains(backupLongTermRetentionPoliciesObj, 'weeklyRetention') ? backupLongTermRetentionPoliciesObj.weeklyRetention : 'P1M' + monthlyRetention: contains(backupLongTermRetentionPoliciesObj, 'monthlyRetention') ? backupLongTermRetentionPoliciesObj.monthlyRetention : 'P1Y' + yearlyRetention: contains(backupLongTermRetentionPoliciesObj, 'yearlyRetention') ? backupLongTermRetentionPoliciesObj.yearlyRetention : 'P5Y' + } +} + +@description('The name of the deployed database') +output name string = database.name + +@description('The resource ID of the deployed database') +output resourceId string = database.id + +@description('The resource group the database was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/readme.md new file mode 100644 index 000000000..c4801c706 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/readme.md @@ -0,0 +1,79 @@ +# SQL Managed Instances Database `[Microsoft.Sql/managedInstances/databases]` + +This template deploys a SQL Managed Instances Database. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/databases` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies` | 2021-02-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies` | 2017-03-01-preview | + +### Deployment prerequisites + +The SQL Managed Instance Database is deployed on a SQL Managed Instance. + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupLongTermRetentionPoliciesObj` | _[backupLongTermRetentionPolicies](backupLongTermRetentionPolicies/readme.md)_ object | `{object}` | | Optional. The configuration for the backup long term retention policy definition | +| `backupShortTermRetentionPoliciesObj` | _[backupShortTermRetentionPolicies](backupShortTermRetentionPolicies/readme.md)_ object | `{object}` | | Optional. The configuration for the backup short term retention policy definition | +| `catalogCollation` | string | `SQL_Latin1_General_CP1_CI_AS` | | Optional. Collation of the managed instance. | +| `collation` | string | `SQL_Latin1_General_CP1_CI_AS` | | Optional. Collation of the managed instance database. | +| `createMode` | string | `Default` | `[Default, RestoreExternalBackup, PointInTimeRestore, Recovery, RestoreLongTermRetentionBackup]` | Optional. Managed database create mode. PointInTimeRestore: Create a database by restoring a point in time backup of an existing database. SourceDatabaseName, SourceManagedInstanceName and PointInTime must be specified. RestoreExternalBackup: Create a database by restoring from external backup files. Collation, StorageContainerUri and StorageContainerSasToken must be specified. Recovery: Creates a database by restoring a geo-replicated backup. RecoverableDatabaseId must be specified as the recoverable database resource ID to restore. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[SQLInsights, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors]` | `[SQLInsights, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors]` | Optional. The name of logs that will be streamed. | +| `longTermRetentionBackupResourceId` | string | | | Optional. Conditional. The name of the Long Term Retention backup to be used for restore of this managed database. | +| `managedInstanceName` | string | | | Required. The name of the SQL managed instance. | +| `name` | string | | | Required. The name of the SQL managed instance database. | +| `recoverableDatabaseId` | string | | | Optional. Conditional. The resource identifier of the recoverable database associated with create operation of this database. | +| `restorableDroppedDatabaseId` | string | | | Optional. Conditional. The restorable dropped database resource ID to restore when creating this database. | +| `restorePointInTime` | string | | | Optional. Conditional. If createMode is PointInTimeRestore, this value is required. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. | +| `sourceDatabaseId` | string | | | Optional. Conditional. The resource identifier of the source database associated with create operation of this database. | +| `storageContainerSasToken` | string | | | Optional. Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the storage container sas token. | +| `storageContainerUri` | string | | | Optional. Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the uri of the storage container where backups for this restore are stored. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database | +| `resourceGroupName` | string | The resource group the database was deployed into | +| `resourceId` | string | The resource ID of the deployed database | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Managedinstances/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/databases) +- [Managedinstances/Databases/Backuplongtermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/databases/backupLongTermRetentionPolicies) +- [Managedinstances/Databases/Backupshorttermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/databases/backupShortTermRetentionPolicies) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/databases/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/databases/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/carml/1.0.0/Microsoft.Sql/managedInstances/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/deploy.bicep new file mode 100644 index 000000000..abb26fa29 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/deploy.bicep @@ -0,0 +1,340 @@ +@description('Required. The name of the SQL managed instance.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The username used to establish jumpbox VMs.') +param administratorLogin string + +@description('Required. The password given to the admin user.') +@secure() +param administratorLoginPassword string + +@description('Required. The fully qualified resource ID of the subnet on which the SQL managed instance will be placed.') +param subnetId string + +@description('Optional. The name of the SKU, typically, a letter + Number code, e.g. P3.') +param skuName string = 'GP_Gen5' + +@description('Optional. The tier or edition of the particular SKU, e.g. Basic, Premium.') +param skuTier string = 'GeneralPurpose' + +@description('Optional. Storage size in GB. Minimum value: 32. Maximum value: 8192. Increments of 32 GB allowed only.') +param storageSizeInGB int = 32 + +@description('Optional. The number of vCores. Allowed values: 8, 16, 24, 32, 40, 64, 80.') +param vCores int = 4 + +@description('Optional. The license type. Possible values are \'LicenseIncluded\' (regular price inclusive of a new SQL license) and \'BasePrice\' (discounted AHB price for bringing your own SQL licenses).') +@allowed([ + 'LicenseIncluded' + 'BasePrice' +]) +param licenseType string = 'LicenseIncluded' + +@description('Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here.') +param hardwareFamily string = 'Gen5' + +@description('Optional. Specifies the mode of database creation. Default: Regular instance creation. Restore: Creates an instance by restoring a set of backups to specific point in time. RestorePointInTime and SourceManagedInstanceId must be specified.') +@allowed([ + 'Default' + 'PointInTimeRestore' +]) +param managedInstanceCreateMode string = 'Default' + +@description('Optional. The resource ID of another managed instance whose DNS zone this managed instance will share after creation.') +param dnsZonePartner string = '' + +@description('Optional. Collation of the managed instance.') +param collation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. Connection type used for connecting to the instance.') +@allowed([ + 'Proxy' + 'Redirect' + 'Default' +]) +param proxyOverride string = 'Proxy' + +@description('Optional. Whether or not the public data endpoint is enabled.') +param publicDataEndpointEnabled bool = false + +@description('Optional. ID of the timezone. Allowed values are timezones supported by Windows.') +param timezoneId string = 'UTC' + +@description('Optional. The resource ID of the instance pool this managed server belongs to.') +param instancePoolResourceId string = '' + +@description('Optional. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database.') +param restorePointInTime string = '' + +@description('Optional. The resource identifier of the source managed instance associated with create operation of this instance.') +param sourceManagedInstanceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Mandatory if "managedServiceIdentity" contains UserAssigned. The resource ID of a user assigned identity to be used by default.') +param primaryUserAssignedIdentityId string = '' + +@description('Optional. Databases to create in this server.') +param databases array = [] + +@description('Optional. The vulnerability assessment configuration') +param vulnerabilityAssessmentsObj object = {} + +@description('Optional. The security alert policy configuration') +param securityAlertPoliciesObj object = {} + +@description('Optional. The keys to configure') +param keys array = [] + +@description('Optional. The encryption protection configuration') +param encryptionProtectorObj object = {} + +@description('Optional. The administrator configuration') +param administratorsObj object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ResourceUsageStats' + 'SQLSecurityAuditEvents' +]) +param logsToEnable array = [ + 'ResourceUsageStats' + 'SQLSecurityAuditEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' = { + name: name + location: location + identity: identity + sku: { + name: skuName + tier: skuTier + } + tags: tags + properties: { + managedInstanceCreateMode: managedInstanceCreateMode + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword + subnetId: subnetId + licenseType: licenseType + hardwareFamily: hardwareFamily + vCores: vCores + storageSizeInGB: storageSizeInGB + collation: collation + dnsZonePartner: dnsZonePartner + publicDataEndpointEnabled: publicDataEndpointEnabled + sourceManagedInstanceId: sourceManagedInstanceId + restorePointInTime: restorePointInTime + proxyOverride: proxyOverride + timezoneId: timezoneId + instancePoolId: instancePoolResourceId + primaryUserAssignedIdentityId: primaryUserAssignedIdentityId + } +} + +resource managedInstance_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${managedInstance.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: managedInstance +} + +resource managedInstance_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${managedInstance.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: managedInstance +} + +module managedInstance_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-SqlMi-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: managedInstance.id + } +}] + +module managedInstance_databases 'databases/deploy.bicep' = [for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-SqlMi-DB-${index}' + params: { + name: database.name + managedInstanceName: managedInstance.name + catalogCollation: contains(database, 'catalogCollation') ? database.catalogCollation : 'SQL_Latin1_General_CP1_CI_AS' + collation: contains(database, 'collation') ? database.collation : 'SQL_Latin1_General_CP1_CI_AS' + createMode: contains(database, 'createMode') ? database.createMode : 'Default' + diagnosticLogsRetentionInDays: contains(database, 'diagnosticLogsRetentionInDays') ? database.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(database, 'diagnosticStorageAccountId') ? database.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(database, 'diagnosticEventHubAuthorizationRuleId') ? database.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(database, 'diagnosticEventHubName') ? database.diagnosticEventHubName : '' + location: contains(database, 'location') ? database.location : managedInstance.location + lock: contains(database, 'lock') ? database.lock : lock + longTermRetentionBackupResourceId: contains(database, 'longTermRetentionBackupResourceId') ? database.longTermRetentionBackupResourceId : '' + recoverableDatabaseId: contains(database, 'recoverableDatabaseId') ? database.recoverableDatabaseId : '' + restorableDroppedDatabaseId: contains(database, 'restorableDroppedDatabaseId') ? database.restorableDroppedDatabaseId : '' + restorePointInTime: contains(database, 'restorePointInTime') ? database.restorePointInTime : '' + sourceDatabaseId: contains(database, 'sourceDatabaseId') ? database.sourceDatabaseId : '' + storageContainerSasToken: contains(database, 'storageContainerSasToken') ? database.storageContainerSasToken : '' + storageContainerUri: contains(database, 'storageContainerUri') ? database.storageContainerUri : '' + tags: contains(database, 'tags') ? database.tags : {} + diagnosticWorkspaceId: contains(database, 'diagnosticWorkspaceId') ? database.diagnosticWorkspaceId : '' + backupShortTermRetentionPoliciesObj: contains(database, 'backupShortTermRetentionPolicies') ? database.backupShortTermRetentionPolicies : {} + backupLongTermRetentionPoliciesObj: contains(database, 'backupLongTermRetentionPolicies') ? database.backupLongTermRetentionPolicies : {} + } +}] + +module managedInstance_securityAlertPolicy 'securityAlertPolicies/deploy.bicep' = if (!empty(securityAlertPoliciesObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-SecAlertPol' + params: { + managedInstanceName: managedInstance.name + name: securityAlertPoliciesObj.name + emailAccountAdmins: contains(securityAlertPoliciesObj, 'emailAccountAdmins') ? securityAlertPoliciesObj.emailAccountAdmins : false + state: contains(securityAlertPoliciesObj, 'state') ? securityAlertPoliciesObj.state : 'Disabled' + } +} + +module managedInstance_vulnerabilityAssessment 'vulnerabilityAssessments/deploy.bicep' = if (!empty(vulnerabilityAssessmentsObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-VulnAssessm' + params: { + managedInstanceName: managedInstance.name + name: vulnerabilityAssessmentsObj.name + recurringScansEmails: contains(vulnerabilityAssessmentsObj, 'recurringScansEmails') ? vulnerabilityAssessmentsObj.recurringScansEmails : [] + recurringScansEmailSubscriptionAdmins: contains(vulnerabilityAssessmentsObj, 'recurringScansEmailSubscriptionAdmins') ? vulnerabilityAssessmentsObj.recurringScansEmailSubscriptionAdmins : false + recurringScansIsEnabled: contains(vulnerabilityAssessmentsObj, 'recurringScansIsEnabled') ? vulnerabilityAssessmentsObj.recurringScansIsEnabled : false + vulnerabilityAssessmentsStorageAccountId: contains(vulnerabilityAssessmentsObj, 'vulnerabilityAssessmentsStorageAccountId') ? vulnerabilityAssessmentsObj.vulnerabilityAssessmentsStorageAccountId : '' + } + dependsOn: [ + managedInstance_securityAlertPolicy + ] +} + +module managedInstance_key 'keys/deploy.bicep' = [for (key, index) in keys: { + name: '${uniqueString(deployment().name, location)}-SqlMi-Key-${index}' + params: { + managedInstanceName: managedInstance.name + name: contains(key, 'name') ? key.name : '' + serverKeyType: contains(key, 'serverKeyType') ? key.serverKeyType : 'ServiceManaged' + uri: contains(key, 'uri') ? key.uri : '' + } +}] + +module managedInstance_encryptionProtector 'encryptionProtector/deploy.bicep' = if (!empty(encryptionProtectorObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-EncryProtector' + params: { + managedInstanceName: managedInstance.name + serverKeyName: contains(encryptionProtectorObj, 'serverKeyName') ? encryptionProtectorObj.serverKeyName : managedInstance_key[0].outputs.name + name: contains(encryptionProtectorObj, 'name') ? encryptionProtectorObj.serverKeyType : 'current' + serverKeyType: contains(encryptionProtectorObj, 'serverKeyType') ? encryptionProtectorObj.serverKeyType : 'ServiceManaged' + autoRotationEnabled: contains(encryptionProtectorObj, 'autoRotationEnabled') ? encryptionProtectorObj.autoRotationEnabled : true + } +} + +module managedInstance_administrator 'administrators/deploy.bicep' = if (!empty(administratorsObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-Admin' + params: { + managedInstanceName: managedInstance.name + login: administratorsObj.name + sid: administratorsObj.name + tenantId: contains(administratorsObj, 'tenantId') ? administratorsObj.tenantId : '' + } +} + +@description('The name of the deployed managed instance') +output name string = managedInstance.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = managedInstance.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(managedInstance.identity, 'principalId') ? managedInstance.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/deploy.bicep new file mode 100644 index 000000000..d78337e1e --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/deploy.bicep @@ -0,0 +1,49 @@ +@description('Required. The name of the encryptionProtector') +param name string = 'current' + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Required. The name of the SQL managed instance key.') +param serverKeyName string + +@description('Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault".') +@allowed([ + 'AzureKeyVault' + 'ServiceManaged' +]) +param serverKeyType string = 'ServiceManaged' + +@description('Optional. Key auto rotation opt-in flag') +param autoRotationEnabled bool = false + +@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 managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource encryptionProtector 'Microsoft.Sql/managedInstances/encryptionProtector@2021-05-01-preview' = { + name: name + parent: managedInstance + properties: { + autoRotationEnabled: autoRotationEnabled + serverKeyName: serverKeyName + serverKeyType: serverKeyType + } +} + +@description('The name of the deployed managed instance') +output name string = encryptionProtector.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = encryptionProtector.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/readme.md new file mode 100644 index 000000000..75818de36 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/readme.md @@ -0,0 +1,32 @@ +# SQL Managed Instance Encryption Protector `[Microsoft.Sql/managedInstances/encryptionProtector]` + +This module deploys an encryption protector for a SQL managed instance. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/encryptionProtector` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `autoRotationEnabled` | bool | | | Optional. Key auto rotation opt-in flag | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `managedInstanceName` | string | | | Required. Name of the SQL managed instance. | +| `name` | string | `current` | | Required. The name of the encryptionProtector | +| `serverKeyName` | string | | | Required. The name of the SQL managed instance key. | +| `serverKeyType` | string | `ServiceManaged` | `[AzureKeyVault, ServiceManaged]` | Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault". | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | + +## Template references + +- [Managedinstances/Encryptionprotector](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/encryptionProtector) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/encryptionProtector/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/carml/1.0.0/Microsoft.Sql/managedInstances/keys/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/keys/deploy.bicep new file mode 100644 index 000000000..09a06b1c3 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/keys/deploy.bicep @@ -0,0 +1,51 @@ +@description('Optional. The name of the key. Must follow the [__] pattern') +param name string = '' + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault"') +@allowed([ + 'AzureKeyVault' + 'ServiceManaged' +]) +param serverKeyType string = 'ServiceManaged' + +@description('Optional. The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required.') +param uri string = '' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var splittedKeyUri = split(uri, '/') + +// if serverManaged, use serverManaged, if uri provided use concated uri value +// MUST match the pattern '__' +var serverKeyName = empty(uri) ? 'ServiceManaged' : '${split(splittedKeyUri[2], '.')[0]}_${splittedKeyUri[4]}_${splittedKeyUri[5]}' + +module pid_cuaId './.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource key 'Microsoft.Sql/managedInstances/keys@2021-05-01-preview' = { + name: !empty(name) ? name : serverKeyName + parent: managedInstance + properties: { + serverKeyType: serverKeyType + uri: uri + } +} + +@description('The name of the deployed managed instance') +output name string = key.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = key.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/keys/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/keys/readme.md new file mode 100644 index 000000000..d8b5e81ef --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/keys/readme.md @@ -0,0 +1,31 @@ +# SQL Managed Instance Keys `[Microsoft.Sql/managedInstances/keys]` + +This module deploys a key for a SQL managed instance. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/keys` | 2021-05-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 | +| `managedInstanceName` | string | | | Required. Name of the SQL managed instance. | +| `name` | string | | | Optional. The name of the key. Must follow the [__] pattern | +| `serverKeyType` | string | `ServiceManaged` | `[AzureKeyVault, ServiceManaged]` | Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault" | +| `uri` | string | | | Optional. The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | + +## Template references + +- [Managedinstances/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/keys) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/keys/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/keys/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/keys/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/carml/1.0.0/Microsoft.Sql/managedInstances/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/readme.md new file mode 100644 index 000000000..6b005da7f --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/readme.md @@ -0,0 +1,156 @@ +# SQL Managed Instances `[Microsoft.Sql/managedInstances]` + +This template deploys a SQL managed instance. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/administrators` | 2021-02-01-preview | +| `Microsoft.Sql/managedInstances/databases` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies` | 2021-02-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies` | 2017-03-01-preview | +| `Microsoft.Sql/managedInstances/encryptionProtector` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/keys` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/securityAlertPolicies` | 2017-03-01-preview | +| `Microsoft.Sql/managedInstances/vulnerabilityAssessments` | 2021-02-01-preview | + +### Deployment prerequisites + +SQL Managed Instance is deployed on a virtual network. This network is required to satisfy the requirements explained [here](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-managed-instance-connectivity-architecture#network-requirements). In the module is a second ARM template UpdateSubnet.deploy.json, which configures a subnet to be ready for the SQL managed instance. + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `administratorLogin` | string | | | Required. The username used to establish jumpbox VMs. | +| `administratorLoginPassword` | secureString | | | Required. The password given to the admin user. | +| `administratorsObj` | _[administrators](administrators/readme.md)_ object | `{object}` | | Optional. The administrator configuration | +| `collation` | string | `SQL_Latin1_General_CP1_CI_AS` | | Optional. Collation of the managed instance. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `databases` | _[databases](databases/readme.md)_ array | `[]` | | Optional. Databases to create in this server. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `dnsZonePartner` | string | | | Optional. The resource ID of another managed instance whose DNS zone this managed instance will share after creation. | +| `encryptionProtectorObj` | _[encryptionProtector](encryptionProtector/readme.md)_ object | `{object}` | | Optional. The encryption protection configuration | +| `hardwareFamily` | string | `Gen5` | | Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| `instancePoolResourceId` | string | | | Optional. The resource ID of the instance pool this managed server belongs to. | +| `keys` | _[keys](keys/readme.md)_ array | `[]` | | Optional. The keys to configure | +| `licenseType` | string | `LicenseIncluded` | `[LicenseIncluded, BasePrice]` | Optional. The license type. Possible values are 'LicenseIncluded' (regular price inclusive of a new SQL license) and 'BasePrice' (discounted AHB price for bringing your own SQL licenses). | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[ResourceUsageStats, SQLSecurityAuditEvents]` | `[ResourceUsageStats, SQLSecurityAuditEvents]` | Optional. The name of logs that will be streamed. | +| `managedInstanceCreateMode` | string | `Default` | `[Default, PointInTimeRestore]` | Optional. Specifies the mode of database creation. Default: Regular instance creation. Restore: Creates an instance by restoring a set of backups to specific point in time. RestorePointInTime and SourceManagedInstanceId must be specified. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the SQL managed instance. | +| `primaryUserAssignedIdentityId` | string | | | Optional. Mandatory if "managedServiceIdentity" contains UserAssigned. The resource ID of a user assigned identity to be used by default. | +| `proxyOverride` | string | `Proxy` | `[Proxy, Redirect, Default]` | Optional. Connection type used for connecting to the instance. | +| `publicDataEndpointEnabled` | bool | | | Optional. Whether or not the public data endpoint is enabled. | +| `restorePointInTime` | string | | | Optional. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityAlertPoliciesObj` | _[securityAlertPolicies](securityAlertPolicies/readme.md)_ object | `{object}` | | Optional. The security alert policy configuration | +| `skuName` | string | `GP_Gen5` | | Optional. The name of the SKU, typically, a letter + Number code, e.g. P3. | +| `skuTier` | string | `GeneralPurpose` | | Optional. The tier or edition of the particular SKU, e.g. Basic, Premium. | +| `sourceManagedInstanceId` | string | | | Optional. The resource identifier of the source managed instance associated with create operation of this instance. | +| `storageSizeInGB` | int | `32` | | Optional. Storage size in GB. Minimum value: 32. Maximum value: 8192. Increments of 32 GB allowed only. | +| `subnetId` | string | | | Required. The fully qualified resource ID of the subnet on which the SQL managed instance will be placed. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `timezoneId` | string | `UTC` | | Optional. ID of the timezone. Allowed values are timezones supported by Windows. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `vCores` | int | `4` | | Optional. The number of vCores. Allowed values: 8, 16, 24, 32, 40, 64, 80. | +| `vulnerabilityAssessmentsObj` | _[vulnerabilityAssessments](vulnerabilityAssessments/readme.md)_ object | `{object}` | | Optional. The vulnerability assessment configuration | + +### Parameter Usage : `userAssignedIdentities` + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Managedinstances](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances) +- [Managedinstances/Administrators](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/administrators) +- [Managedinstances/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/databases) +- [Managedinstances/Databases/Backuplongtermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/databases/backupLongTermRetentionPolicies) +- [Managedinstances/Databases/Backupshorttermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/databases/backupShortTermRetentionPolicies) +- [Managedinstances/Encryptionprotector](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/encryptionProtector) +- [Managedinstances/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/keys) +- [Managedinstances/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/securityAlertPolicies) +- [Managedinstances/Vulnerabilityassessments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/vulnerabilityAssessments) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/deploy.bicep new file mode 100644 index 000000000..c1e0a92d8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/deploy.bicep @@ -0,0 +1,45 @@ +@description('Required. The name of the security alert policy') +param name string + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. Enables advanced data security features, like recuring vulnerability assesment scans and ATP. If enabled, storage account must be provided.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param state string = 'Disabled' + +@description('Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators.') +param emailAccountAdmins bool = false + +@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 managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource securityAlertPolicy 'Microsoft.Sql/managedInstances/securityAlertPolicies@2017-03-01-preview' = { + name: name + parent: managedInstance + properties: { + state: state + emailAccountAdmins: emailAccountAdmins + } +} + +@description('The name of the deployed security alert policy') +output name string = securityAlertPolicy.name + +@description('The resource ID of the deployed security alert policy') +output resourceId string = securityAlertPolicy.id + +@description('The resource group of the deployed security alert policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/readme.md new file mode 100644 index 000000000..c739262e8 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/readme.md @@ -0,0 +1,31 @@ +# SQL Managed Instance Security Alert Policy `[Microsoft.Sql/managedInstances/securityAlertPolicies]` + +This module deploys a security alert policy for a SQL managed instance. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/securityAlertPolicies` | 2017-03-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 | +| `emailAccountAdmins` | bool | | | Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators. | +| `managedInstanceName` | string | | | Required. Name of the SQL managed instance. | +| `name` | string | | | Required. The name of the security alert policy | +| `state` | string | `Disabled` | `[Enabled, Disabled]` | Optional. Enables advanced data security features, like recuring vulnerability assesment scans and ATP. If enabled, storage account must be provided. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed security alert policy | +| `resourceId` | string | The resource ID of the deployed security alert policy | +| `resourceGroupName` | string | The resource group of the deployed security alert policy | + +## Template references + +- [Managedinstances/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/securityAlertPolicies) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/securityAlertPolicies/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/carml/1.0.0/Microsoft.Sql/managedInstances/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/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/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/deploy.bicep b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/deploy.bicep new file mode 100644 index 000000000..f044ac3f3 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. The name of the vulnerability assessment') +param name string + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. Recurring scans state.') +param recurringScansIsEnabled bool = false + +@description('Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators.') +param recurringScansEmailSubscriptionAdmins bool = false + +@description('Optional. Specifies an array of email addresses to which the scan notification is sent.') +param recurringScansEmails array = [] + +@description('Optional. A blob storage to hold the scan results.') +param vulnerabilityAssessmentsStorageAccountId string = '' + +@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 managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource vulnerabilityAssessment 'Microsoft.Sql/managedInstances/vulnerabilityAssessments@2021-02-01-preview' = { + name: name + parent: managedInstance + properties: { + storageContainerPath: 'https://${last(split(vulnerabilityAssessmentsStorageAccountId, '/'))}.blob.${environment().suffixes.storage}/vulnerability-assessment/' + storageAccountAccessKey: listKeys(vulnerabilityAssessmentsStorageAccountId, '2019-06-01').keys[0].value + recurringScans: { + isEnabled: recurringScansIsEnabled + emailSubscriptionAdmins: recurringScansEmailSubscriptionAdmins + emails: recurringScansEmails + } + } +} + +@description('The name of the deployed vulnerability assessment') +output name string = vulnerabilityAssessment.name + +@description('The resource ID of the deployed vulnerability assessment') +output resourceId string = vulnerabilityAssessment.id + +@description('The resource group of the deployed vulnerability assessment') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/readme.md b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/readme.md new file mode 100644 index 000000000..153d661eb --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/readme.md @@ -0,0 +1,33 @@ +# SQL Managed Instance Vulnerability Assessments `[Microsoft.Sql/managedInstances/vulnerabilityAssessments]` + +This module deploys a vulnerability assessment for a SQL managed instance. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/vulnerabilityAssessments` | 2021-02-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 | +| `managedInstanceName` | string | | | Required. Name of the SQL managed instance. | +| `name` | string | | | Required. The name of the vulnerability assessment | +| `recurringScansEmails` | array | `[]` | | Optional. Specifies an array of email addresses to which the scan notification is sent. | +| `recurringScansEmailSubscriptionAdmins` | bool | | | Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators. | +| `recurringScansIsEnabled` | bool | | | Optional. Recurring scans state. | +| `vulnerabilityAssessmentsStorageAccountId` | string | | | Optional. A blob storage to hold the scan results. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed vulnerability assessment | +| `resourceId` | string | The resource ID of the deployed vulnerability assessment | +| `resourceGroupName` | string | The resource group of the deployed vulnerability assessment | + +## Template references + +- [Managedinstances/Vulnerabilityassessments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/vulnerabilityAssessments) diff --git a/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/version.json b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/managedInstances/vulnerabilityAssessments/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/carml/1.0.0/Microsoft.Sql/servers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/servers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/servers/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Sql/servers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..93a78da85 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'SQL Server Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource server 'Microsoft.Sql/servers@2020-02-02-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(server.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: server +}] diff --git a/carml/1.0.0/Microsoft.Sql/servers/.parameters/parameters.json b/carml/1.0.0/Microsoft.Sql/servers/.parameters/parameters.json new file mode 100644 index 000000000..47bf627cb --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/.parameters/parameters.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "administratorLogin": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/<>/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLogin" + } + }, + "administratorLoginPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/<>/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLoginPassword" + } + }, + "location": { + "value": "westeurope" + }, + "name": { + "value": "<>-az-sqlsrv-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "databases": { + "value": [ + { + "name": "<>-az-sqldb-x-001", + "collation": "SQL_Latin1_General_CP1_CI_AS", + "tier": "GeneralPurpose", + "skuName": "GP_Gen5_2", + "maxSizeBytes": 34359738368, + "licenseType": "LicenseIncluded", + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "eventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "eventHubName": "adp-<>-az-evh-x-001" + } + ] + }, + "firewallRules": { + "value": [ + { + "name": "AllowAllWindowsAzureIps", + "endIpAddress": "0.0.0.0", + "startIpAddress": "0.0.0.0" + } + ] + }, + "securityAlertPolicies": { + "value": [ + { + "name": "Default", + "state": "Enabled", + "emailAccountAdmins": true + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Sql/servers/databases/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/servers/databases/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/databases/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/servers/databases/deploy.bicep b/carml/1.0.0/Microsoft.Sql/servers/databases/deploy.bicep new file mode 100644 index 000000000..09d7c6acc --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/databases/deploy.bicep @@ -0,0 +1,190 @@ +@description('Optional. The collation of the database.') +param collation string + +@description('Required. The name of the database.') +param name string + +@description('Optional. The tier or edition of the particular SKU.') +param tier string + +@description('Required. The name of the SKU.') +param skuName string + +@description('Optional. The max size of the database expressed in bytes.') +param maxSizeBytes int + +@description('Required. The Name of SQL Server') +param serverName string + +@description('Optional. The name of the sample schema to apply when creating this database.') +param sampleName string = '' + +@description('Optional. Whether or not this database is zone redundant.') +param zoneRedundant bool = false + +@description('Optional. The license type to apply for this database.') +param licenseType string = '' + +@description('Optional. The state of read-only routing.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param readScale string = 'Disabled' + +@description('Optional. The number of readonly secondary replicas associated with the database.') +param highAvailabilityReplicaCount int = 0 + +@description('Optional. Minimal capacity that database will always have allocated.') +param minCapacity string = '' + +@description('Optional. Time in minutes after which database is automatically paused.') +param autoPauseDelay string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'SQLInsights' + 'AutomaticTuning' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' + 'DatabaseWaitStatistics' + 'Timouts' + 'Blocks' + 'Deadlocks' +]) +param logsToEnable array = [ + 'SQLInsights' + 'AutomaticTuning' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' + 'DatabaseWaitStatistics' + 'Timouts' + 'Blocks' + 'Deadlocks' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Basic' +]) +param metricsToEnable array = [ + 'Basic' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@description('Optional. The storage account type to be used to store backups for this database.') +@allowed([ + 'Geo' + 'Local' + 'Zone' + '' +]) +param requestedBackupStorageRedundancy string = '' + +@description('Optional. Whether or not this database is a ledger database, which means all tables in the database are ledger tables. Note: the value of this property cannot be changed after the database has been created.') +param isLedgerOn bool = false + +@description('Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur.') +param maintenanceConfigurationId string = '' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource server 'Microsoft.Sql/servers@2021-05-01-preview' existing = { + name: serverName +} + +resource database 'Microsoft.Sql/servers/databases@2021-02-01-preview' = { + name: name + parent: server + location: location + tags: tags + properties: { + collation: collation + maxSizeBytes: maxSizeBytes + sampleName: sampleName + zoneRedundant: zoneRedundant + licenseType: licenseType + readScale: readScale + minCapacity: !empty(minCapacity) ? json(minCapacity) : 0 + autoPauseDelay: !empty(autoPauseDelay) ? json(autoPauseDelay) : 0 + highAvailabilityReplicaCount: highAvailabilityReplicaCount + requestedBackupStorageRedundancy: any(requestedBackupStorageRedundancy) + isLedgerOn: isLedgerOn + maintenanceConfigurationId: !empty(maintenanceConfigurationId) ? maintenanceConfigurationId : null + } + sku: { + name: skuName + tier: tier + } +} + +resource database_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${last(split(database.name, '/'))}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: database +} + +@description('The name of the deployed database') +output name string = database.name + +@description('The resource ID of the deployed database') +output resourceId string = database.id + +@description('The resourceGroup of the deployed database') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/servers/databases/readme.md b/carml/1.0.0/Microsoft.Sql/servers/databases/readme.md new file mode 100644 index 000000000..9110cd7e1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/databases/readme.md @@ -0,0 +1,71 @@ +# SQL Server Database `[Microsoft.Sql/servers/databases]` + +This module deploys an Azure SQL Server. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/servers/databases` | 2021-02-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `autoPauseDelay` | string | | | Optional. Time in minutes after which database is automatically paused. | +| `collation` | string | | | Optional. The collation of the database. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `highAvailabilityReplicaCount` | int | | | Optional. The number of readonly secondary replicas associated with the database. | +| `isLedgerOn` | bool | | | Optional. Whether or not this database is a ledger database, which means all tables in the database are ledger tables. Note: the value of this property cannot be changed after the database has been created. | +| `licenseType` | string | | | Optional. The license type to apply for this database. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `logsToEnable` | array | `[SQLInsights, AutomaticTuning, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors, DatabaseWaitStatistics, Timouts, Blocks, Deadlocks]` | `[SQLInsights, AutomaticTuning, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors, DatabaseWaitStatistics, Timouts, Blocks, Deadlocks]` | Optional. The name of logs that will be streamed. | +| `maintenanceConfigurationId` | string | | | Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur. | +| `maxSizeBytes` | int | | | Optional. The max size of the database expressed in bytes. | +| `metricsToEnable` | array | `[Basic]` | `[Basic]` | Optional. The name of metrics that will be streamed. | +| `minCapacity` | string | | | Optional. Minimal capacity that database will always have allocated. | +| `name` | string | | | Required. The name of the database. | +| `readScale` | string | `Disabled` | `[Enabled, Disabled]` | Optional. The state of read-only routing. | +| `requestedBackupStorageRedundancy` | string | | `[Geo, Local, Zone, ]` | Optional. The storage account type to be used to store backups for this database. | +| `sampleName` | string | | | Optional. The name of the sample schema to apply when creating this database. | +| `serverName` | string | | | Required. The Name of SQL Server | +| `skuName` | string | | | Required. The name of the SKU. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `tier` | string | | | Optional. The tier or edition of the particular SKU. | +| `zoneRedundant` | bool | | | Optional. Whether or not this database is zone redundant. | + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database | +| `resourceGroupName` | string | The resourceGroup of the deployed database | +| `resourceId` | string | The resource ID of the deployed database | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Servers/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/servers/databases) diff --git a/carml/1.0.0/Microsoft.Sql/servers/databases/version.json b/carml/1.0.0/Microsoft.Sql/servers/databases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/databases/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/carml/1.0.0/Microsoft.Sql/servers/deploy.bicep b/carml/1.0.0/Microsoft.Sql/servers/deploy.bicep new file mode 100644 index 000000000..06787626f --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/deploy.bicep @@ -0,0 +1,154 @@ +@description('Required. Administrator username for the server.') +param administratorLogin string + +@description('Required. The administrator login password.') +@secure() +param administratorLoginPassword string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The name of the server.') +param name string + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The databases to create in the server') +param databases array = [] + +@description('Optional. The firewall rules to create in the server') +param firewallRules array = [] + +@description('Optional. The security alert policies to create in the server') +param securityAlertPolicies array = [] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource server 'Microsoft.Sql/servers@2021-05-01-preview' = { + location: location + name: name + tags: tags + identity: identity + properties: { + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword + version: '12.0' + } +} + +resource server_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${server.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: server +} + +module server_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Sql-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: server.id + } +}] + +module server_databases 'databases/deploy.bicep' = [for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-Sql-DB-${index}' + params: { + name: database.name + serverName: server.name + maxSizeBytes: database.maxSizeBytes + tier: database.tier + skuName: database.skuName + collation: database.collation + autoPauseDelay: contains(database, 'autoPauseDelay') ? database.autoPauseDelay : '' + diagnosticLogsRetentionInDays: contains(database, 'diagnosticLogsRetentionInDays') ? database.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(database, 'diagnosticStorageAccountId') ? database.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(database, 'diagnosticEventHubAuthorizationRuleId') ? database.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(database, 'diagnosticEventHubName') ? database.diagnosticEventHubName : '' + isLedgerOn: contains(database, 'isLedgerOn') ? database.isLedgerOn : false + location: contains(database, 'location') ? database.location : server.location + logsToEnable: contains(database, 'logsToEnable') ? database.logsToEnable : [] + licenseType: contains(database, 'licenseType') ? database.licenseType : '' + maintenanceConfigurationId: contains(database, 'maintenanceConfigurationId') ? database.maintenanceConfigurationId : '' + minCapacity: contains(database, 'minCapacity') ? database.minCapacity : '' + metricsToEnable: contains(database, 'metricsToEnable') ? database.metricsToEnable : [] + highAvailabilityReplicaCount: contains(database, 'highAvailabilityReplicaCount') ? database.highAvailabilityReplicaCount : 0 + readScale: contains(database, 'readScale') ? database.readScale : 'Disabled' + requestedBackupStorageRedundancy: contains(database, 'requestedBackupStorageRedundancy') ? database.requestedBackupStorageRedundancy : '' + sampleName: contains(database, 'sampleName') ? database.sampleName : '' + tags: contains(database, 'tags') ? database.tags : {} + diagnosticWorkspaceId: contains(database, 'diagnosticWorkspaceId') ? database.diagnosticWorkspaceId : '' + zoneRedundant: contains(database, 'zoneRedundant') ? database.zoneRedundant : false + } +}] + +module server_firewallRules 'firewallRules/deploy.bicep' = [for (firewallRule, index) in firewallRules: { + name: '${uniqueString(deployment().name, location)}-Sql-FirewallRules-${index}' + params: { + name: firewallRule.name + serverName: server.name + endIpAddress: contains(firewallRule, 'endIpAddress') ? firewallRule.endIpAddress : '0.0.0.0' + startIpAddress: contains(firewallRule, 'startIpAddress') ? firewallRule.startIpAddress : '0.0.0.0' + } +}] + +module server_securityAlertPolicies 'securityAlertPolicies/deploy.bicep' = [for (securityAlertPolicy, index) in securityAlertPolicies: { + name: '${uniqueString(deployment().name, location)}-Sql-SecAlertPolicy-${index}' + params: { + name: securityAlertPolicy.name + serverName: server.name + disabledAlerts: contains(securityAlertPolicy, 'disabledAlerts') ? securityAlertPolicy.disabledAlerts : [] + emailAccountAdmins: contains(securityAlertPolicy, 'emailAccountAdmins') ? securityAlertPolicy.emailAccountAdmins : false + emailAddresses: contains(securityAlertPolicy, 'emailAddresses') ? securityAlertPolicy.emailAddresses : [] + retentionDays: contains(securityAlertPolicy, 'retentionDays') ? securityAlertPolicy.retentionDays : 0 + state: contains(securityAlertPolicy, 'state') ? securityAlertPolicy.state : 'Disabled' + storageAccountAccessKey: contains(securityAlertPolicy, 'storageAccountAccessKey') ? securityAlertPolicy.storageAccountAccessKey : '' + storageEndpoint: contains(securityAlertPolicy, 'storageEndpoint') ? securityAlertPolicy.storageEndpoint : '' + } +}] + +@description('The name of the deployed SQL server') +output name string = server.name + +@description('The resource ID of the deployed SQL server') +output resourceId string = server.id + +@description('The resourceGroup of the deployed SQL server') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(server.identity, 'principalId') ? server.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Sql/servers/firewallRules/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/servers/firewallRules/deploy.bicep b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/deploy.bicep new file mode 100644 index 000000000..e56973fb1 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/deploy.bicep @@ -0,0 +1,41 @@ +@description('Required. The name of the Server Firewall Rule.') +param name string + +@description('Optional. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') +param endIpAddress string = '0.0.0.0' + +@description('Optional. The start IP address of the firewall rule. Must be IPv4 format. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') +param startIpAddress string = '0.0.0.0' + +@description('Required. The Name of SQL Server') +param serverName string + +@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 server 'Microsoft.Sql/servers@2021-05-01-preview' existing = { + name: serverName +} + +resource firewallRule 'Microsoft.Sql/servers/firewallRules@2021-05-01-preview' = { + name: name + parent: server + properties: { + endIpAddress: endIpAddress + startIpAddress: startIpAddress + } +} + +@description('The name of the deployed firewall rule') +output name string = firewallRule.name + +@description('The resource ID of the deployed firewall rule') +output resourceId string = firewallRule.id + +@description('The resourceGroup of the deployed firewall rule') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/servers/firewallRules/readme.md b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/readme.md new file mode 100644 index 000000000..862650690 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/readme.md @@ -0,0 +1,31 @@ +# SQL Server Firewall rule `[Microsoft.Sql/servers/firewallrules]` + +This module deploys an SQL Server Firewall rule. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/servers/firewallRules` | 2021-05-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 | +| `endIpAddress` | string | `0.0.0.0` | | Optional. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. | +| `name` | string | | | Required. The name of the Server Firewall Rule. | +| `serverName` | string | | | Required. The Name of SQL Server | +| `startIpAddress` | string | `0.0.0.0` | | Optional. The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed firewall rule | +| `resourceGroupName` | string | The resourceGroup of the deployed firewall rule | +| `resourceId` | string | The resource ID of the deployed firewall rule | + +## Template references + +- [Servers/Firewallrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/firewallRules) diff --git a/carml/1.0.0/Microsoft.Sql/servers/firewallRules/version.json b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/firewallRules/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/carml/1.0.0/Microsoft.Sql/servers/readme.md b/carml/1.0.0/Microsoft.Sql/servers/readme.md new file mode 100644 index 000000000..5d0527784 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/readme.md @@ -0,0 +1,104 @@ +# SQL Servers `[Microsoft.Sql/servers]` + +This module deploys a SQL server. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/servers` | 2021-05-01-preview | +| `Microsoft.Sql/servers/databases` | 2021-02-01-preview | +| `Microsoft.Sql/servers/firewallRules` | 2021-05-01-preview | +| `Microsoft.Sql/servers/securityAlertPolicies` | 2021-05-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `administratorLogin` | string | | | Required. Administrator username for the server. | +| `administratorLoginPassword` | secureString | | | Required. The administrator login password. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `databases` | _[databases](databases/readme.md)_ array | `[]` | | Optional. The databases to create in the server | +| `firewallRules` | _[firewallRules](firewallRules/readme.md)_ array | `[]` | | Optional. The firewall rules to create in the server | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the server. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityAlertPolicies` | _[securityAlertPolicies](securityAlertPolicies/readme.md)_ array | `[]` | | Optional. The security alert policies to create in the server | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed SQL server | +| `resourceGroupName` | string | The resourceGroup of the deployed SQL server | +| `resourceId` | string | The resource ID of the deployed SQL server | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Servers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers) +- [Servers/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/servers/databases) +- [Servers/Firewallrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/firewallRules) +- [Servers/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/securityAlertPolicies) diff --git a/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/deploy.bicep new file mode 100644 index 000000000..81d2ef6d4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/deploy.bicep @@ -0,0 +1,66 @@ +@description('Required. The name of the Security Alert Policy.') +param name string + +@description('Optional. Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force.') +param disabledAlerts array = [] + +@description('Optional. Specifies that the alert is sent to the account administrators.') +param emailAccountAdmins bool = false + +@description('Optional. Specifies an array of email addresses to which the alert is sent.') +param emailAddresses array = [] + +@description('Optional. Specifies the number of days to keep in the Threat Detection audit logs.') +param retentionDays int = 0 + +@description('Optional. Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param state string = 'Disabled' + +@description('Optional. Specifies the identifier key of the Threat Detection audit storage account..') +@secure() +param storageAccountAccessKey string = '' + +@description('Optional. Specifies the blob storage endpoint (e.g. https://mystorageaccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs.') +param storageEndpoint string = '' + +@description('Required. The Name of SQL Server') +param serverName string + +@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 server 'Microsoft.Sql/servers@2021-05-01-preview' existing = { + name: serverName +} + +resource securityAlertPolicy 'Microsoft.Sql/servers/securityAlertPolicies@2021-05-01-preview' = { + name: name + parent: server + properties: { + disabledAlerts: disabledAlerts + emailAccountAdmins: emailAccountAdmins + emailAddresses: emailAddresses + retentionDays: retentionDays + state: state + storageAccountAccessKey: empty(storageAccountAccessKey) ? null : storageAccountAccessKey + storageEndpoint: empty(storageEndpoint) ? null : storageEndpoint + } +} + +@description('The name of the deployed security alert policy') +output name string = securityAlertPolicy.name + +@description('The resource ID of the deployed security alert policy') +output resourceId string = securityAlertPolicy.id + +@description('The resourceGroup of the deployed security alert policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/readme.md b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/readme.md new file mode 100644 index 000000000..a2fb1b5f7 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/readme.md @@ -0,0 +1,36 @@ +# SQL Server Security Alert Policy `[Microsoft.Sql/servers/securityAlertPolicies]` + +This module deploys an SQL Server Security Alert Policy. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/servers/securityAlertPolicies` | 2021-05-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 | +| `disabledAlerts` | array | `[]` | | Optional. Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force. | +| `emailAccountAdmins` | bool | | | Optional. Specifies that the alert is sent to the account administrators. | +| `emailAddresses` | array | `[]` | | Optional. Specifies an array of email addresses to which the alert is sent. | +| `name` | string | | | Required. The name of the Security Alert Policy. | +| `retentionDays` | int | | | Optional. Specifies the number of days to keep in the Threat Detection audit logs. | +| `serverName` | string | | | Required. The Name of SQL Server | +| `state` | string | `Disabled` | `[Disabled, Enabled]` | Optional. Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database. | +| `storageAccountAccessKey` | secureString | | | Optional. Specifies the identifier key of the Threat Detection audit storage account.. | +| `storageEndpoint` | string | | | Optional. Specifies the blob storage endpoint (e.g. https://mystorageaccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed security alert policy | +| `resourceGroupName` | string | The resourceGroup of the deployed security alert policy | +| `resourceId` | string | The resource ID of the deployed security alert policy | + +## Template references + +- [Servers/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/securityAlertPolicies) diff --git a/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/version.json b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/securityAlertPolicies/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/carml/1.0.0/Microsoft.Sql/servers/version.json b/carml/1.0.0/Microsoft.Sql/servers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Sql/servers/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/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..75fa03bcd --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateDnsZoneGroups 'privateDnsZoneGroups@2021-02-01' = { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + } +} diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e611b0f42 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(storageAccount.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: storageAccount +}] diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..30ac50db6 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "allowBlobPublicAccess": { + "value": false + } + } +} diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/parameters.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/parameters.json new file mode 100644 index 000000000..f7dd17774 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/parameters.json @@ -0,0 +1,176 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsax001" + }, + "storageAccountSku": { + "value": "Standard_LRS" + }, + "allowBlobPublicAccess": { + "value": false + }, + "requireInfrastructureEncryption": { + "value": true + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "blob" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "table" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "queue" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "file" + } + ] + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "blobServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "eventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "eventHubName": "adp-<>-az-evh-x-001", + "containers": [ + { + "name": "avdscripts", + "publicAccess": "None", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "archivecontainer", + "publicAccess": "None", + "enableWORM": true, + "WORMRetention": 666, + "allowProtectedAppendWrites": false + } + ] + } + }, + "fileServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "eventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "eventHubName": "adp-<>-az-evh-x-001", + "shares": [ + { + "name": "avdprofiles", + "shareQuota": "5120", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "avdprofiles2", + "shareQuota": "5120" + } + ] + } + }, + "tableServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "eventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "eventHubName": "adp-<>-az-evh-x-001", + "tables": [ + "table1", + "table2" + ] + } + }, + "queueServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "eventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "eventHubName": "adp-<>-az-evh-x-001", + "queues": [ + { + "name": "queue1", + "metadata": {}, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "queue2", + "metadata": {} + } + ] + } + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json new file mode 100644 index 000000000..c411287f9 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "storageAccountKind": { + "value": "Storage" + }, + "allowBlobPublicAccess": { + "value": false + } + } +} diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..3db79286a --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep @@ -0,0 +1,50 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(container.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: container +}] diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep new file mode 100644 index 000000000..a23c16829 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep @@ -0,0 +1,79 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. The name of the storage container to deploy') +param name string + +@description('Optional. Name of the immutable policy.') +param immutabilityPolicyName string = 'default' + +@allowed([ + 'Container' + 'Blob' + 'None' +]) +@description('Optional. Specifies whether data in the container may be accessed publicly and the level of access.') +param publicAccess string = 'None' + +@description('Optional. Configure immutability policy.') +param immutabilityPolicyProperties object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + } +} + +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' = { + name: name + parent: storageAccount::blobServices + properties: { + publicAccess: publicAccess + } +} + +module immutabilityPolicy 'immutabilityPolicies/deploy.bicep' = if (!empty(immutabilityPolicyProperties)) { + name: immutabilityPolicyName + params: { + storageAccountName: storageAccount.name + blobServicesName: storageAccount::blobServices.name + containerName: container.name + immutabilityPeriodSinceCreationInDays: contains(immutabilityPolicyProperties, 'immutabilityPeriodSinceCreationInDays') ? immutabilityPolicyProperties.immutabilityPeriodSinceCreationInDays : 365 + allowProtectedAppendWrites: contains(immutabilityPolicyProperties, 'allowProtectedAppendWrites') ? immutabilityPolicyProperties.allowProtectedAppendWrites : true + } +} + +module container_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: container.id + } +}] + +@description('The name of the deployed container') +output name string = container.name + +@description('The resource ID of the deployed container') +output resourceId string = container.id + +@description('The resource group of the deployed container') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep new file mode 100644 index 000000000..0137bc945 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep @@ -0,0 +1,56 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. Name of the container to apply the policy to') +param containerName string + +@description('Optional. Name of the immutable policy.') +param name string = 'default' + +@description('Optional. The immutability period for the blobs in the container since the policy creation, in days.') +param immutabilityPeriodSinceCreationInDays int = 365 + +@description('Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API') +param allowProtectedAppendWrites bool = true + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + + resource container 'containers@2019-06-01' existing = { + name: containerName + } + } +} + +resource immutabilityPolicy 'Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2019-06-01' = { + name: name + parent: storageAccount::blobServices::container + properties: { + immutabilityPeriodSinceCreationInDays: immutabilityPeriodSinceCreationInDays + allowProtectedAppendWrites: allowProtectedAppendWrites + } +} + +@description('The name of the deployed immutability policy.') +output name string = immutabilityPolicy.name + +@description('The resource ID of the deployed immutability policy.') +output resourceId string = immutabilityPolicy.id + +@description('The resource group of the deployed immutability policy.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md new file mode 100644 index 000000000..e4780fd50 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md @@ -0,0 +1,33 @@ +# Blob Container Immutability Policy `[Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies]` + +This module deployes an Immutability Policy for a blob container + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowProtectedAppendWrites` | bool | `True` | | Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API | +| `blobServicesName` | string | `default` | | Optional. Name of the blob service. | +| `containerName` | string | | | Required. Name of the container to apply the policy to | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `immutabilityPeriodSinceCreationInDays` | int | `365` | | Optional. The immutability period for the blobs in the container since the policy creation, in days. | +| `name` | string | `default` | | Optional. Name of the immutable policy. | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed immutability policy. | +| `resourceGroupName` | string | The resource group of the deployed immutability policy. | +| `resourceId` | string | The resource ID of the deployed immutability policy. | + +## Template references + +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/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/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md new file mode 100644 index 000000000..431d6d710 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md @@ -0,0 +1,60 @@ +# Storage Account Container `[Microsoft.Storage/storageAccounts/blobServices/containers]` + +This module deployes a blob container + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `blobServicesName` | string | `default` | | Optional. Name of the blob service. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `immutabilityPolicyName` | string | `default` | | Optional. Name of the immutable policy. | +| `immutabilityPolicyProperties` | object | `{object}` | | Optional. Configure immutability policy. | +| `name` | string | | | Required. The name of the storage container to deploy | +| `publicAccess` | string | `None` | `[Container, Blob, None]` | Optional. Specifies whether data in the container may be accessed publicly and the level of access. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed container | +| `resourceGroupName` | string | The resource group of the deployed container | +| `resourceId` | string | The resource ID of the deployed container | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/containers/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/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep new file mode 100644 index 000000000..898c8252c --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep @@ -0,0 +1,132 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the blob service') +param name string = 'default' + +@description('Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service.') +param deleteRetentionPolicy bool = true + +@description('Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365.') +param deleteRetentionPolicyDays int = 7 + +@description('Optional. Automatic Snapshot is enabled if set to true.') +param automaticSnapshotPolicyEnabled bool = false + +@description('Optional. Blob containers to create.') +param containers array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param logsToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param metricsToEnable array = [ + 'Transaction' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource blobServices 'Microsoft.Storage/storageAccounts/blobServices@2021-06-01' = { + name: name + parent: storageAccount + properties: { + deleteRetentionPolicy: { + enabled: deleteRetentionPolicy + days: deleteRetentionPolicyDays + } + automaticSnapshotPolicyEnabled: automaticSnapshotPolicyEnabled + } +} + +resource blobServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${blobServices.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: blobServices +} + +module blobServices_container 'containers/deploy.bicep' = [for (container, index) in containers: { + name: '${deployment().name}-Container-${index}' + params: { + storageAccountName: storageAccount.name + blobServicesName: blobServices.name + name: container.name + publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None' + roleAssignments: contains(container, 'roleAssignments') ? container.roleAssignments : [] + immutabilityPolicyProperties: contains(container, 'immutabilityPolicyProperties') ? container.immutabilityPolicyProperties : {} + } +}] + +@description('The name of the deployed blob service') +output name string = blobServices.name + +@description('The resource ID of the deployed blob service') +output resourceId string = blobServices.id + +@description('The name of the deployed blob service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/deploy.bicep new file mode 100644 index 000000000..0137bc945 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/deploy.bicep @@ -0,0 +1,56 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. Name of the container to apply the policy to') +param containerName string + +@description('Optional. Name of the immutable policy.') +param name string = 'default' + +@description('Optional. The immutability period for the blobs in the container since the policy creation, in days.') +param immutabilityPeriodSinceCreationInDays int = 365 + +@description('Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API') +param allowProtectedAppendWrites bool = true + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + + resource container 'containers@2019-06-01' existing = { + name: containerName + } + } +} + +resource immutabilityPolicy 'Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2019-06-01' = { + name: name + parent: storageAccount::blobServices::container + properties: { + immutabilityPeriodSinceCreationInDays: immutabilityPeriodSinceCreationInDays + allowProtectedAppendWrites: allowProtectedAppendWrites + } +} + +@description('The name of the deployed immutability policy.') +output name string = immutabilityPolicy.name + +@description('The resource ID of the deployed immutability policy.') +output resourceId string = immutabilityPolicy.id + +@description('The resource group of the deployed immutability policy.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/readme.md new file mode 100644 index 000000000..e4780fd50 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/readme.md @@ -0,0 +1,33 @@ +# Blob Container Immutability Policy `[Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies]` + +This module deployes an Immutability Policy for a blob container + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowProtectedAppendWrites` | bool | `True` | | Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API | +| `blobServicesName` | string | `default` | | Optional. Name of the blob service. | +| `containerName` | string | | | Required. Name of the container to apply the policy to | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `immutabilityPeriodSinceCreationInDays` | int | `365` | | Optional. The immutability period for the blobs in the container since the policy creation, in days. | +| `name` | string | `default` | | Optional. Name of the immutable policy. | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed immutability policy. | +| `resourceGroupName` | string | The resource group of the deployed immutability policy. | +| `resourceId` | string | The resource ID of the deployed immutability policy. | + +## Template references + +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/immutabilityPolicies/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/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/readme.md new file mode 100644 index 000000000..fabfe8413 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/readme.md @@ -0,0 +1,48 @@ +# Storage Account blob services `[Microsoft.Storage/storageAccounts/blobServices]` + +This module can be used to deploy a blob service into a storage account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/blobServices` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automaticSnapshotPolicyEnabled` | bool | | | Optional. Automatic Snapshot is enabled if set to true. | +| `containers` | _[containers](containers/readme.md)_ array | `[]` | | Optional. Blob containers to create. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `deleteRetentionPolicy` | bool | `True` | | Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service. | +| `deleteRetentionPolicyDays` | int | `7` | | Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of a log analytics workspace. | +| `logsToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[Transaction]` | `[Transaction]` | Optional. The name of metrics that will be streamed. | +| `name` | string | `default` | | Optional. The name of the blob service | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed blob service | +| `resourceGroupName` | string | The name of the deployed blob service | +| `resourceId` | string | The resource ID of the deployed blob service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Blobservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/blobServices) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/blobServices/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/carml/1.0.0/Microsoft.Storage/storageAccounts/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/deploy.bicep new file mode 100644 index 000000000..fab95df51 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/deploy.bicep @@ -0,0 +1,340 @@ +@maxLength(24) +@description('Optional. Name of the Storage Account.') +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'Storage' + 'StorageV2' + 'BlobStorage' + 'FileStorage' + 'BlockBlobStorage' +]) +@description('Optional. Type of Storage Account to create.') +param storageAccountKind string = 'StorageV2' + +@allowed([ + 'Standard_LRS' + 'Standard_GRS' + 'Standard_RAGRS' + 'Standard_ZRS' + 'Premium_LRS' + 'Premium_ZRS' + 'Standard_GZRS' + 'Standard_RAGZRS' +]) +@description('Optional. Storage Account Sku Name.') +param storageAccountSku string = 'Standard_GRS' + +@allowed([ + 'Hot' + 'Cool' +]) +@description('Optional. Storage Account Access Tier.') +param storageAccountAccessTier string = 'Hot' + +@description('Optional. Provides the identity based authentication settings for Azure Files.') +param azureFilesIdentityBasedAuthentication object = {} + +@description('Optional. Virtual Network Identifier used to create a service endpoint.') +param vNetId string = '' + +@description('Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible') +param privateEndpoints array = [] + +@description('Optional. The Storage Account ManagementPolicies Rules.') +param managementPolicyRules array = [] + +@description('Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny') +param networkAcls object = {} + +@description('Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true.') +param requireInfrastructureEncryption bool = true + +@description('Optional. Blob service and containers to deploy') +param blobServices object = {} + +@description('Optional. File service and shares to deploy') +param fileServices object = {} + +@description('Optional. Queue service and queues to create.') +param queueServices object = {} + +@description('Optional. Table service and tables to create.') +param tableServices object = {} + +@description('Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false.') +param allowBlobPublicAccess bool = false + +@allowed([ + 'TLS1_0' + 'TLS1_1' + 'TLS1_2' +]) +@description('Optional. Set the minimum TLS version on request to storage.') +param minimumTlsVersion string = 'TLS1_2' + +@description('Optional. If true, enables Hierarchical Namespace for the storage account') +param enableHierarchicalNamespace bool = false + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param basetime string = utcNow('u') + +@description('Optional. Allows https traffic only to storage service if sets to true.') +param supportsHttpsTrafficOnly bool = true + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param metricsToEnable array = [ + 'Transaction' +] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var virtualNetworkRules = [for index in range(0, (empty(networkAcls) ? 0 : length(networkAcls.virtualNetworkRules))): { + id: '${vNetId}/subnets/${networkAcls.virtualNetworkRules[index].subnet}' +}] +var networkAcls_var = { + bypass: (empty(networkAcls) ? null : networkAcls.bypass) + defaultAction: (empty(networkAcls) ? null : networkAcls.defaultAction) + virtualNetworkRules: (empty(networkAcls) ? null : virtualNetworkRules) + ipRules: (empty(networkAcls) ? null : ((length(networkAcls.ipRules) == 0) ? null : networkAcls.ipRules)) +} +var azureFilesIdentityBasedAuthentication_var = azureFilesIdentityBasedAuthentication + +var maxNameLength = 24 +var uniqueStoragenameUntrim = '${uniqueString('Storage Account${basetime}')}' +var uniqueStoragename = length(uniqueStoragenameUntrim) > maxNameLength ? substring(uniqueStoragenameUntrim, 0, maxNameLength) : uniqueStoragenameUntrim + +var saBaseProperties = { + encryption: { + keySource: 'Microsoft.Storage' + services: { + blob: (((storageAccountKind == 'BlockBlobStorage') || (storageAccountKind == 'BlobStorage') || (storageAccountKind == 'StorageV2') || (storageAccountKind == 'Storage')) ? json('{"enabled": true}') : null) + file: (((storageAccountKind == 'FileStorage') || (storageAccountKind == 'StorageV2') || (storageAccountKind == 'Storage')) ? json('{"enabled": true}') : null) + } + } + accessTier: (storageAccountKind == 'Storage') ? null : storageAccountAccessTier + supportsHttpsTrafficOnly: supportsHttpsTrafficOnly + isHnsEnabled: ((!enableHierarchicalNamespace) ? null : enableHierarchicalNamespace) + minimumTlsVersion: minimumTlsVersion + networkAcls: (empty(networkAcls) ? null : networkAcls_var) + allowBlobPublicAccess: allowBlobPublicAccess + requireInfrastructureEncryption: requireInfrastructureEncryption +} +var saOptIdBasedAuthProperties = { + azureFilesIdentityBasedAuthentication: azureFilesIdentityBasedAuthentication_var +} +var saProperties = (empty(azureFilesIdentityBasedAuthentication) ? saBaseProperties : union(saBaseProperties, saOptIdBasedAuthProperties)) + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = { + name: !empty(name) ? name : uniqueStoragename + location: location + kind: storageAccountKind + sku: { + name: storageAccountSku + } + identity: identity + tags: tags + properties: saProperties +} + +resource storageAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${storageAccount.name}-diagnosticSettings' + properties: { + storageAccountId: empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId + workspaceId: empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId + eventHubAuthorizationRuleId: empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId + eventHubName: empty(diagnosticEventHubName) ? null : diagnosticEventHubName + metrics: diagnosticsMetrics + } + scope: storageAccount +} + +resource storageAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${storageAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: storageAccount +} + +module storageAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Storage-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: storageAccount.id + } +}] + +module storageAccount_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-Storage-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: storageAccount.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: endpoint + tags: tags + } +}] + +// Lifecycle Policy +module storageAccount_managementPolicies 'managementPolicies/deploy.bicep' = if (!empty(managementPolicyRules)) { + name: '${uniqueString(deployment().name, location)}-Storage-ManagementPolicies' + params: { + storageAccountName: storageAccount.name + rules: managementPolicyRules + } +} + +// Containers +module storageAccount_blobServices 'blobServices/deploy.bicep' = if (!empty(blobServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-BlobServices' + params: { + storageAccountName: storageAccount.name + containers: contains(blobServices, 'containers') ? blobServices.containers : [] + automaticSnapshotPolicyEnabled: contains(blobServices, 'automaticSnapshotPolicyEnabled') ? blobServices.automaticSnapshotPolicyEnabled : false + deleteRetentionPolicy: contains(blobServices, 'deleteRetentionPolicy') ? blobServices.deleteRetentionPolicy : true + deleteRetentionPolicyDays: contains(blobServices, 'deleteRetentionPolicyDays') ? blobServices.deleteRetentionPolicyDays : 7 + diagnosticLogsRetentionInDays: contains(blobServices, 'diagnosticLogsRetentionInDays') ? blobServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(blobServices, 'diagnosticStorageAccountId') ? blobServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(blobServices, 'diagnosticEventHubAuthorizationRuleId') ? blobServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(blobServices, 'diagnosticEventHubName') ? blobServices.diagnosticEventHubName : '' + logsToEnable: contains(blobServices, 'logsToEnable') ? blobServices.logsToEnable : [] + metricsToEnable: contains(blobServices, 'metricsToEnable') ? blobServices.metricsToEnable : [] + diagnosticWorkspaceId: contains(blobServices, 'diagnosticWorkspaceId') ? blobServices.diagnosticWorkspaceId : '' + } +} + +// File Shares +module storageAccount_fileServices 'fileServices/deploy.bicep' = if (!empty(fileServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-FileServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(fileServices, 'diagnosticLogsRetentionInDays') ? fileServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(fileServices, 'diagnosticStorageAccountId') ? fileServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(fileServices, 'diagnosticEventHubAuthorizationRuleId') ? fileServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(fileServices, 'diagnosticEventHubName') ? fileServices.diagnosticEventHubName : '' + logsToEnable: contains(fileServices, 'logsToEnable') ? fileServices.logsToEnable : [] + metricsToEnable: contains(fileServices, 'metricsToEnable') ? fileServices.metricsToEnable : [] + protocolSettings: contains(fileServices, 'protocolSettings') ? fileServices.protocolSettings : {} + shareDeleteRetentionPolicy: contains(fileServices, 'shareDeleteRetentionPolicy') ? fileServices.shareDeleteRetentionPolicy : { + enabled: true + days: 7 + } + shares: contains(fileServices, 'shares') ? fileServices.shares : [] + diagnosticWorkspaceId: contains(fileServices, 'diagnosticWorkspaceId') ? fileServices.diagnosticWorkspaceId : '' + } +} + +// Queue +module storageAccount_queueServices 'queueServices/deploy.bicep' = if (!empty(queueServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-QueueServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(queueServices, 'diagnosticLogsRetentionInDays') ? queueServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(queueServices, 'diagnosticStorageAccountId') ? queueServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(queueServices, 'diagnosticEventHubAuthorizationRuleId') ? queueServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(queueServices, 'diagnosticEventHubName') ? queueServices.diagnosticEventHubName : '' + logsToEnable: contains(queueServices, 'logsToEnable') ? queueServices.logsToEnable : [] + metricsToEnable: contains(queueServices, 'metricsToEnable') ? queueServices.metricsToEnable : [] + queues: contains(queueServices, 'queues') ? queueServices.queues : [] + diagnosticWorkspaceId: contains(queueServices, 'diagnosticWorkspaceId') ? queueServices.diagnosticWorkspaceId : '' + } +} + +// Table +module storageAccount_tableServices 'tableServices/deploy.bicep' = if (!empty(tableServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-TableServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(tableServices, 'diagnosticLogsRetentionInDays') ? tableServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(tableServices, 'diagnosticStorageAccountId') ? tableServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(tableServices, 'diagnosticEventHubAuthorizationRuleId') ? tableServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(tableServices, 'diagnosticEventHubName') ? tableServices.diagnosticEventHubName : '' + logsToEnable: contains(tableServices, 'logsToEnable') ? tableServices.logsToEnable : [] + metricsToEnable: contains(tableServices, 'metricsToEnable') ? tableServices.metricsToEnable : [] + tables: contains(tableServices, 'tables') ? tableServices.tables : [] + diagnosticWorkspaceId: contains(tableServices, 'diagnosticWorkspaceId') ? tableServices.diagnosticWorkspaceId : '' + } +} + +@description('The resource ID of the deployed storage account') +output resourceId string = storageAccount.id + +@description('The name of the deployed storage account') +output name string = storageAccount.name + +@description('The resource group of the deployed storage account') +output resourceGroupName string = resourceGroup().name + +@description('The primary blob endpoint reference if blob services are deployed.') +output primaryBlobEndpoint string = !empty(blobServices) && contains(blobServices, 'containers') ? reference('Microsoft.Storage/storageAccounts/${storageAccount.name}', '2019-04-01').primaryEndpoints.blob : '' + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(storageAccount.identity, 'principalId') ? storageAccount.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep new file mode 100644 index 000000000..838a8539a --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep @@ -0,0 +1,128 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the file service') +param name string = 'default' + +@description('Optional. Protocol settings for file service') +param protocolSettings object = {} + +@description('Optional. The service properties for soft delete.') +param shareDeleteRetentionPolicy object = { + enabled: true + days: 7 +} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. File shares to create.') +param shares array = [] + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param logsToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param metricsToEnable array = [ + 'Transaction' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource fileServices 'Microsoft.Storage/storageAccounts/fileServices@2021-04-01' = { + name: name + parent: storageAccount + properties: { + protocolSettings: protocolSettings + shareDeleteRetentionPolicy: shareDeleteRetentionPolicy + } +} + +resource fileServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${fileServices.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: fileServices +} + +module fileServices_shares 'shares/deploy.bicep' = [for (share, index) in shares: { + name: '${deployment().name}-File-${index}' + params: { + storageAccountName: storageAccount.name + fileServicesName: fileServices.name + name: share.name + sharedQuota: contains(share, 'sharedQuota') ? share.sharedQuota : 5120 + roleAssignments: contains(share, 'roleAssignments') ? share.roleAssignments : [] + } +}] + +@description('The name of the deployed file share service') +output name string = fileServices.name + +@description('The resource ID of the deployed file share service') +output resourceId string = fileServices.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/readme.md new file mode 100644 index 000000000..a0b2e5776 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/readme.md @@ -0,0 +1,45 @@ +# Storage Account file share services `[Microsoft.Storage/storageAccounts/fileServices]` + +This module can be used to deploy a file share service into a storage account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/fileServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of a log analytics workspace. | +| `logsToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[Transaction]` | `[Transaction]` | Optional. The name of metrics that will be streamed. | +| `name` | string | `default` | | Optional. The name of the file service | +| `protocolSettings` | object | `{object}` | | Optional. Protocol settings for file service | +| `shareDeleteRetentionPolicy` | object | `{object}` | | Optional. The service properties for soft delete. | +| `shares` | _[shares](shares/readme.md)_ array | `[]` | | Optional. File shares to create. | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Fileservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/fileServices) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/fileServices/shares) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6a91451e2 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(fileShare.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: fileShare +}] diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep new file mode 100644 index 000000000..5c19a0f04 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep @@ -0,0 +1,57 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the file service') +param fileServicesName string = 'default' + +@description('Required. The name of the file share to create') +param name string + +@description('Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400.') +param sharedQuota int = 5120 + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource fileService 'fileServices@2021-04-01' existing = { + name: fileServicesName + } +} + +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2019-06-01' = { + name: name + parent: storageAccount::fileService + properties: { + shareQuota: sharedQuota + } +} + +module fileShare_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: fileShare.id + } +}] + +@description('The name of the deployed file share') +output name string = fileShare.name + +@description('The resource ID of the deployed file share') +output resourceId string = fileShare.id + +@description('The resource group of the deployed file share') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md new file mode 100644 index 000000000..1ce7b8757 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md @@ -0,0 +1,56 @@ +# File Share `[Microsoft.Storage/storageAccounts/fileServices/shares]` + +This module deploys a storage account file share. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `fileServicesName` | string | `default` | | Optional. The name of the file service | +| `name` | string | | | Required. The name of the file share to create | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sharedQuota` | int | `5120` | | Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400. | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share | +| `resourceGroupName` | string | The resource group of the deployed file share | +| `resourceId` | string | The resource ID of the deployed file share | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/fileServices/shares) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/shares/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/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/fileServices/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/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep new file mode 100644 index 000000000..739e341aa --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep @@ -0,0 +1,41 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the storage container to deploy') +param name string = 'default' + +@description('Required. The Storage Account ManagementPolicies Rules') +param rules array + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +// lifecycle policy +resource managementPolicy 'Microsoft.Storage/storageAccounts/managementPolicies@2019-06-01' = if (!empty(rules)) { + name: name + parent: storageAccount + properties: { + policy: { + rules: rules + } + } +} + +@description('The resource ID of the deployed management policy') +output resourceId string = managementPolicy.name + +@description('The name of the deployed management policy') +output name string = managementPolicy.name + +@description('The resource group of the deployed management policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/readme.md new file mode 100644 index 000000000..a7b9d4a67 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/readme.md @@ -0,0 +1,64 @@ +# Storage Account Management Policies `[Microsoft.Storage/storageAccounts/managementPolicies]` + +This module can be used to deploy a management policies into a storage account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/managementPolicies` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | `default` | | Optional. The name of the storage container to deploy | +| `rules` | array | | | Required. The Storage Account ManagementPolicies Rules | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +### Parameter Usage: `rules` + +```json +[ + { + "enabled": true, + "name": "retention-policy", + "type": "Lifecycle", + "definition": { + "actions": { + "baseBlob": { + "tierToArchive": { + "daysAfterModificationGreaterThan": 30 + }, + "delete": { + "daysAfterModificationGreaterThan": 1096 + } + }, + "snapshot": { + "delete": { + "daysAfterCreationGreaterThan": 1096 + } + } + }, + "filters": { + "blobTypes": [ + "blockBlob" + ] + } + } + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed management policy | +| `resourceGroupName` | string | The resource group of the deployed management policy | +| `resourceId` | string | The resource ID of the deployed management policy | + +## Template references + +- [Storageaccounts/Managementpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/managementPolicies) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/managementPolicies/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/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep new file mode 100644 index 000000000..4566df0ec --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep @@ -0,0 +1,116 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the queue service') +param name string = 'default' + +@description('Optional. Queues to create.') +param queues array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param logsToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param metricsToEnable array = [ + 'Transaction' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource queueServices 'Microsoft.Storage/storageAccounts/queueServices@2021-04-01' = { + name: name + parent: storageAccount + properties: {} +} + +resource queueServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${queueServices.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: queueServices +} + +module queueServices_queues 'queues/deploy.bicep' = [for (queue, index) in queues: { + name: '${deployment().name}-Queue-${index}' + params: { + storageAccountName: storageAccount.name + queueServicesName: queueServices.name + name: queue.name + metadata: contains(queue, 'metadata') ? queue.metadata : {} + roleAssignments: contains(queue, 'roleAssignments') ? queue.roleAssignments : [] + } +}] + +@description('The name of the deployed file share service') +output name string = queueServices.name + +@description('The resource ID of the deployed file share service') +output resourceId string = queueServices.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..fd1dfa435 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Dsms Role (deprecated)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b') + 'Dsms Role (do not use)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f') + 'GenevaWarmPathResourceContributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource queue 'Microsoft.Storage/storageAccounts/queueServices/queues@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queue.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: queue +}] diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep new file mode 100644 index 000000000..a0b866575 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep @@ -0,0 +1,57 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the queue service') +param queueServicesName string = 'default' + +@description('Required. The name of the storage queue to deploy') +param name string + +@description('Required. A name-value pair that represents queue metadata.') +param metadata object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource queueServices 'queueServices@2021-06-01' existing = { + name: queueServicesName + } +} + +resource queue 'Microsoft.Storage/storageAccounts/queueServices/queues@2019-06-01' = { + name: name + parent: storageAccount::queueServices + properties: { + metadata: metadata + } +} + +module queue_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: '${queue.id}' + } +}] + +@description('The name of the deployed queue') +output name string = queue.name + +@description('The resource ID of the deployed queue') +output resourceId string = queue.id + +@description('The resource group of the deployed queue') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md new file mode 100644 index 000000000..e1988be29 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md @@ -0,0 +1,56 @@ +# Storage Account Queue `[Microsoft.Storage/storageAccounts/queueServices/queues]` + +This module deployes a storage account queue + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `metadata` | object | `{object}` | | Required. A name-value pair that represents queue metadata. | +| `name` | string | | | Required. The name of the storage queue to deploy | +| `queueServicesName` | string | `default` | | Optional. The name of the queue service | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed queue | +| `resourceGroupName` | string | The resource group of the deployed queue | +| `resourceId` | string | The resource ID of the deployed queue | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/queues/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/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/readme.md new file mode 100644 index 000000000..7b87611be --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/readme.md @@ -0,0 +1,43 @@ +# Storage Account Queue Services `[Microsoft.Storage/storageAccounts/queueServices]` + +This module can be used to deploy a file share service into a storage account. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/queueServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of a log analytics workspace. | +| `logsToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[Transaction]` | `[Transaction]` | Optional. The name of metrics that will be streamed. | +| `name` | string | `default` | | Optional. The name of the queue service | +| `queues` | _[queues](queues/readme.md)_ array | `[]` | | Optional. Queues to create. | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Queueservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/queueServices) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/queueServices/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/carml/1.0.0/Microsoft.Storage/storageAccounts/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/readme.md new file mode 100644 index 000000000..cc59f8636 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/readme.md @@ -0,0 +1,200 @@ +# Storage Accounts `[Microsoft.Storage/storageAccounts]` + +This module is used to deploy a storage account, with the ability to deploy 1 or more blob containers, file shares, tables and queues. Optional ACLs can be configured on the storage account and optional RBAC can be assigned on the storage account and on each child resource. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | +| `Microsoft.Storage/storageAccounts` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/fileServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/managementPolicies` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/queueServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/tableServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBlobPublicAccess` | bool | `False` | | Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false. | +| `azureFilesIdentityBasedAuthentication` | object | `{object}` | | Optional. Provides the identity based authentication settings for Azure Files. | +| `basetime` | string | `[utcNow('u')]` | | Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules. | +| `blobServices` | _[blobServices](blobServices/readme.md)_ object | `{object}` | | Optional. Blob service and containers to deploy | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `enableHierarchicalNamespace` | bool | `False` | | Optional. If true, enables Hierarchical Namespace for the storage account | +| `fileServices` | _[fileServices](fileServices/readme.md)_ object | `{object}` | | Optional. File service and shares to deploy | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `managementPolicyRules` | array | `[]` | | Optional. The Storage Account ManagementPolicies Rules. | +| `metricsToEnable` | array | `[Transaction]` | `[Transaction]` | Optional. The name of metrics that will be streamed. | +| `minimumTlsVersion` | string | `TLS1_2` | `[TLS1_0, TLS1_1, TLS1_2]` | Optional. Set the minimum TLS version on request to storage. | +| `name` | string | | | Optional. Name of the Storage Account. | +| `networkAcls` | object | `{object}` | | Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible | +| `queueServices` | _[queueServices](queueServices/readme.md)_ object | `{object}` | | Optional. Queue service and queues to create. | +| `requireInfrastructureEncryption` | bool | `True` | | Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `storageAccountAccessTier` | string | `Hot` | `[Hot, Cool]` | Optional. Storage Account Access Tier. | +| `storageAccountKind` | string | `StorageV2` | `[Storage, StorageV2, BlobStorage, FileStorage, BlockBlobStorage]` | Optional. Type of Storage Account to create. | +| `storageAccountSku` | string | `Standard_GRS` | `[Standard_LRS, Standard_GRS, Standard_RAGRS, Standard_ZRS, Premium_LRS, Premium_ZRS, Standard_GZRS, Standard_RAGZRS]` | Optional. Storage Account Sku Name. | +| `supportsHttpsTrafficOnly` | bool | `True` | | Optional. Allows https traffic only to storage service if sets to true. | +| `systemAssignedIdentity` | bool | `False` | | Optional. Enables system assigned managed identity on the resource. | +| `tableServices` | _[tableServices](tableServices/readme.md)_ object | `{object}` | | Optional. Table service and tables to create. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | +| `vNetId` | string | | | Optional. Virtual Network Identifier used to create a service endpoint. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "subnet": "sharedsvcs" + } + ], + "ipRules": [] + } +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed storage account | +| `primaryBlobEndpoint` | string | The primary blob endpoint reference if blob services are deployed. | +| `resourceGroupName` | string | The resource group of the deployed storage account | +| `resourceId` | string | The resource ID of the deployed storage account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +This is a generic module for deploying a Storage Account. Any customization for different storage needs (such as a diagnostic or other storage account) need to be done through the Archetype. +The hierarchical namespace of the storage account (see parameter `enableHierarchicalNamespace`), can be only set at creation time. + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts) +- [Storageaccounts/Blobservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/blobServices) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) +- [Storageaccounts/Fileservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/fileServices) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/fileServices/shares) +- [Storageaccounts/Managementpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/managementPolicies) +- [Storageaccounts/Queueservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/queueServices) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) +- [Storageaccounts/Tableservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/tableServices) +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep new file mode 100644 index 000000000..fb535f769 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep @@ -0,0 +1,114 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the table service') +param name string = 'default' + +@description('Optional. tables to create.') +param tables array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param logsToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param metricsToEnable array = [ + 'Transaction' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource tableServices 'Microsoft.Storage/storageAccounts/tableServices@2021-04-01' = { + name: name + parent: storageAccount + properties: {} +} + +resource tableServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${tableServices.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: tableServices +} + +module tableServices_tables 'tables/deploy.bicep' = [for (tableName, index) in tables: { + name: '${deployment().name}-Table-${index}' + params: { + storageAccountName: storageAccount.name + tableServicesName: tableServices.name + name: tableName + } +}] + +@description('The name of the deployed table service') +output name string = tableServices.name + +@description('The resource ID of the deployed table service') +output resourceId string = tableServices.id + +@description('The resource group of the deployed table service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/readme.md new file mode 100644 index 000000000..b1945d05f --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/readme.md @@ -0,0 +1,41 @@ +# Storage Account Table Services `[Microsoft.Storage/storageAccounts/tableServices]` + +This module deploys a storage account table service + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/tableServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of a log analytics workspace. | +| `logsToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[Transaction]` | `[Transaction]` | Optional. The name of metrics that will be streamed. | +| `name` | string | `default` | | Optional. The name of the table service | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | +| `tables` | _[tables](tables/readme.md)_ array | `[]` | | Optional. tables to create. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed table service | +| `resourceGroupName` | string | The resource group of the deployed table service | +| `resourceId` | string | The resource ID of the deployed table service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Storageaccounts/Tableservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/tableServices) +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep new file mode 100644 index 000000000..1f81be35c --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep @@ -0,0 +1,39 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the table service') +param tableServicesName string = 'default' + +@description('Required. Name of the table.') +param name string + +@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 storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource tableServices 'tableServices@2021-04-01' existing = { + name: tableServicesName + } +} + +resource table 'Microsoft.Storage/storageAccounts/tableServices/tables@2021-06-01' = { + name: name + parent: storageAccount::tableServices +} + +@description('The name of the deployed file share service') +output name string = table.name + +@description('The resource ID of the deployed file share service') +output resourceId string = table.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md new file mode 100644 index 000000000..9c0e3e040 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md @@ -0,0 +1,30 @@ +# Storage Account Table `[Microsoft.Storage/storageAccounts/tableServices/tables]` + +This module deploys a storage account table + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `name` | string | | | Required. Name of the table. | +| `storageAccountName` | string | | | Required. Name of the Storage Account. | +| `tableServicesName` | string | `default` | | Optional. The name of the table service | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/tables/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/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/tableServices/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/carml/1.0.0/Microsoft.Storage/storageAccounts/version.json b/carml/1.0.0/Microsoft.Storage/storageAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Storage/storageAccounts/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/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..f855b992b --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,50 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}' + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : [] + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + parent: privateEndpoint +} diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..07993ec01 --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateLinkHub 'Microsoft.Synapse/privateLinkHubs@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateLinkHub.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: privateLinkHub +}] diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.parameters/min.parameters.json b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.parameters/min.parameters.json new file mode 100644 index 000000000..8b3b8868e --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "synplhmin001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.parameters/parameters.json b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.parameters/parameters.json new file mode 100644 index 000000000..e9bb15fdb --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/.parameters/parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "synplhstandard001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": ["<>"] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "principalIds": ["<>"] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/deploy.bicep b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/deploy.bicep new file mode 100644 index 000000000..2b44faff0 --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/deploy.bicep @@ -0,0 +1,68 @@ +@description('Required. The name of the Private Link Hub.') +param name string + +@description('Optional. The geo-location where the resource lives.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +resource privateLinkHub 'Microsoft.Synapse/privateLinkHubs@2021-06-01' = { + name: name + location: location + tags: tags +} + +// Resource Lock +resource privateLinkHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateLinkHub.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateLinkHub +} + +// RBAC +module privateLinkHub_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateLinkHub.id + } +}] + +// Private Endpoints +module privateLinkHub_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: privateLinkHub.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The resource ID of the deployed Synapse Private Link Hub.') +output resourceId string = privateLinkHub.id + +@description('The name of the deployed Synapse Private Link Hub.') +output name string = privateLinkHub.name + +@description('The resource group of the deployed Synapse Private Link Hub.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/readme.md b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/readme.md new file mode 100644 index 000000000..e4b6ab030 --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/readme.md @@ -0,0 +1,115 @@ +# Synapse PrivateLinkHubs `[Microsoft.Synapse/privateLinkHubs]` + +This module deploys Synapse PrivateLinkHubs. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.Synapse/privateLinkHubs` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `location` | string | `[resourceGroup().location]` | | Optional. The geo-location where the resource lives. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. The name of the Private Link Hub. | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed Synapse Private Link Hub. | +| `resourceGroupName` | string | The resource group of the deployed Synapse Private Link Hub. | +| `resourceId` | string | The resource ID of the deployed Synapse Private Link Hub. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints/privateDnsZoneGroups) +- [Privatelinkhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Synapse/2021-06-01/privateLinkHubs) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/version.json b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Synapse/privateLinkHubs/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/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..f0e426170 --- /dev/null +++ b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep @@ -0,0 +1,32 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2020-02-14' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(imageTemplate.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: imageTemplate +}] diff --git a/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.parameters/parameters.json b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.parameters/parameters.json new file mode 100644 index 000000000..4b1b66c31 --- /dev/null +++ b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/.parameters/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": "<>-az-imgt-x-001" + }, + "userMsiName": { + "value": "adp-<>-az-msi-x-001" + }, + "userMsiResourceGroup": { + "value": "validation-rg" + }, + "buildTimeoutInMinutes": { + "value": 0 + }, + "vmSize": { + "value": "Standard_D2s_v3" + }, + "osDiskSizeGB": { + "value": 127 + }, + "subnetId": { + "value": "" + }, + "imageSource": { + "value": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-10", + "sku": "19h2-evd", + "version": "latest" + } + }, + "customizationSteps": { + "value": [ + { + "type": "WindowsRestart", + "restartTimeout": "30m" + } + ] + }, + "managedImageName": { + "value": "<>-az-mi-x-001" + }, + "unManagedImageName": { + "value": "<>-az-umi-x-001" + }, + "sigImageDefinitionId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/galleries/adp<>azsigweux001/images/adp-<>-az-imgd-x-001" + }, + "imageReplicationRegions": { + "value": [] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep new file mode 100644 index 000000000..84dd37173 --- /dev/null +++ b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep @@ -0,0 +1,179 @@ +@description('Required. Name of the Image Template to be built by the Azure Image Builder service.') +param name string + +@description('Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder.') +param userMsiName string + +@description('Optional. Resource group of the user assigned identity.') +param userMsiResourceGroup string = resourceGroup().name + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes') +@minValue(0) +@maxValue(960) +param buildTimeoutInMinutes int = 0 + +@description('Optional. Specifies the size for the VM.') +param vmSize string = 'Standard_D2s_v3' + +@description('Optional. Specifies the size of OS disk.') +param osDiskSizeGB int = 128 + +@description('Optional. Resource ID of an already existing subnet, e.g. \'/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/\'. If no value is provided, a new VNET will be created in the target Resource Group.') +param subnetId string = '' + +@description('Required. Image source definition in object format.') +param imageSource object + +@description('Required. Customization steps to be run when building the VM image.') +param customizationSteps array + +@description('Optional. Name of the managed image that will be created in the AIB resourcegroup.') +param managedImageName string = '' + +@description('Optional. Name of the unmanaged image that will be created in the AIB resourcegroup.') +param unManagedImageName string = '' + +@description('Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/') +param sigImageDefinitionId string = '' + +@description('Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment\'s location will be taken as a default value.') +param imageReplicationRegions array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +var managedImageName_var = '${managedImageName}-${baseTime}' +var managedImageId = '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Compute/images/${managedImageName_var}' +var imageReplicationRegions_var = empty(imageReplicationRegions) ? array(location) : imageReplicationRegions + +var managedImage = { + type: 'ManagedImage' + imageId: managedImageId + location: location + runOutputName: '${managedImageName_var}-ManagedImage' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } +} +var conditionalManagedImage = empty(managedImageName) ? [] : array(managedImage) +var sharedImage = { + type: 'SharedImage' + galleryImageId: sigImageDefinitionId + runOutputName: !empty(sigImageDefinitionId) ? '${split(sigImageDefinitionId, '/')[10]}-SharedImage' : 'SharedImage' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } + replicationRegions: imageReplicationRegions_var +} +var conditionalSharedImage = empty(sigImageDefinitionId) ? [] : array(sharedImage) +var unManagedImage = { + type: 'VHD' + runOutputName: '${unManagedImageName}-VHD' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } +} +var conditionalUnManagedImage = empty(unManagedImageName) ? [] : array(unManagedImage) +var distribute = concat(conditionalManagedImage, conditionalSharedImage, conditionalUnManagedImage) +var vnetConfig = { + subnetId: subnetId +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2020-02-14' = { + name: '${name}-${baseTime}' + location: location + tags: tags + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${az.resourceId(userMsiResourceGroup, 'Microsoft.ManagedIdentity/userAssignedIdentities', userMsiName)}': {} + } + } + properties: { + buildTimeoutInMinutes: buildTimeoutInMinutes + vmProfile: { + vmSize: vmSize + osDiskSizeGB: osDiskSizeGB + vnetConfig: !empty(subnetId) ? vnetConfig : null + } + source: imageSource + customize: customizationSteps + distribute: distribute + } +} + +resource imageTemplate_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${imageTemplate.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: imageTemplate +} + +module imageTemplate_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ImageTemplate-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: imageTemplate.id + } +}] + +@description('The resource ID of the image template') +output resourceId string = imageTemplate.id + +@description('The resource group the image template was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image template') +output name string = imageTemplate.name + +@description('The command to run in order to trigger the image build') +output runThisCommand string = 'Invoke-AzResourceAction -ResourceName ${imageTemplate.name} -ResourceGroupName ${resourceGroup().name} -ResourceType Microsoft.VirtualMachineImages/imageTemplates -Action Run -Force' diff --git a/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/readme.md b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/readme.md new file mode 100644 index 000000000..7b7897d5a --- /dev/null +++ b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/readme.md @@ -0,0 +1,123 @@ +# Image Templates `[Microsoft.VirtualMachineImages/imageTemplates]` + +This module deploys an image template that can be consumed by the Azure Image Builder (AIB) service. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.VirtualMachineImages/imageTemplates` | 2020-02-14 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('yyyy-MM-dd-HH-mm-ss')]` | | Generated. Do not provide a value! This date value is used to generate a unique image template name. | +| `buildTimeoutInMinutes` | int | | | Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `customizationSteps` | array | | | Required. Customization steps to be run when building the VM image. | +| `imageReplicationRegions` | array | `[]` | | Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment's location will be taken as a default value. | +| `imageSource` | object | | | Required. Image source definition in object format. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `managedImageName` | string | | | Optional. Name of the managed image that will be created in the AIB resourcegroup. | +| `name` | string | | | Required. Name of the Image Template to be built by the Azure Image Builder service. | +| `osDiskSizeGB` | int | `128` | | Optional. Specifies the size of OS disk. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sigImageDefinitionId` | string | | | Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/ | +| `subnetId` | string | | | Optional. Resource ID of an already existing subnet, e.g. '/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/'. If no value is provided, a new VNET will be created in the target Resource Group. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `unManagedImageName` | string | | | Optional. Name of the unmanaged image that will be created in the AIB resourcegroup. | +| `userMsiName` | string | | | Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder. | +| `userMsiResourceGroup` | string | `[resourceGroup().name]` | | Optional. Resource group of the user assigned identity. | +| `vmSize` | string | `Standard_D2s_v3` | | Optional. Specifies the size for the VM. | + +### Parameter Usage: `imageSource` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +#### Platform Image + +```json +"source": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-10", + "sku": "19h2-evd", + "version": "latest" +} +``` + +#### Managed Image + +```json +"source": { + "type": "ManagedImage", + "imageId": "/subscriptions//resourceGroups/{destinationResourceGroupName}/providers/Microsoft.Compute/images/" +} +``` + +#### Shared Image + +```json +"source": { + "type": "SharedImageVersion", + "imageVersionID": "/subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/" +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image template | +| `resourceGroupName` | string | The resource group the image template was deployed into | +| `resourceId` | string | The resource ID of the image template | +| `runThisCommand` | string | The command to run in order to trigger the image build | + +## Template references + +- [Define resources with Bicep and ARM templates](https://docs.microsoft.com/en-us/azure/templates) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/version.json b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/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/carml/1.0.0/Microsoft.Web/connections/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Web/connections/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/connections/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Web/connections/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Web/connections/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e4f4db74c --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/connections/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource connection 'Microsoft.Web/connections@2016-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(connection.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: connection +}] diff --git a/carml/1.0.0/Microsoft.Web/connections/.parameters/parameters.json b/carml/1.0.0/Microsoft.Web/connections/.parameters/parameters.json new file mode 100644 index 000000000..920f8784b --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/connections/.parameters/parameters.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "azuremonitor" + }, + "connectionKind": { + "value": "V1" + }, + "displayName": { + "value": "azuremonitorlogs" + }, + "connectionApi": { + "value": { + "id": "/subscriptions/<>/providers/Microsoft.Web/locations/westeurope/managedApis/azuremonitorlogs" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/connections/deploy.bicep b/carml/1.0.0/Microsoft.Web/connections/deploy.bicep new file mode 100644 index 000000000..2f9aac136 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/connections/deploy.bicep @@ -0,0 +1,103 @@ +@description('Optional. Alternative parameter values.') +param alternativeParameterValues object = {} + +@description('Optional. Specific values for some API connections.') +param connectionApi object = {} + +@description('Required. Connection Kind. Example: \'V1\' when using blobs. It can change depending on the resource.') +param connectionKind string + +@description('Required. Connection name for connection. Example: \'azureblob\' when using blobs. It can change depending on the resource.') +param name string + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +@description('Optional. Customized parameter values for specific connections.') +param customParameterValues object = {} + +@description('Required. Display name connection. Example: \'blobconnection\' when using blobs. It can change depending on the resource.') +param displayName string + +@description('Optional. Location of the deployment.') +param location string = resourceGroup().location + +@description('Optional. Dictionary of nonsecret parameter values.') +param nonSecretParameterValues object = {} + +@description('Optional. Connection strings or access keys for connection. Example: \'accountName\' and \'accessKey\' when using blobs. It can change depending on the resource.') +@secure() +param parameterValues object = {} + +@description('Optional. Value Type of parameter, in case alternativeParameterValues is used.') +param parameterValueType string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Status of the connection.') +param statuses array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Links to test the API connection.') +param testLinks array = [] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource connection 'Microsoft.Web/connections@2016-06-01' = { + name: name + location: location + kind: connectionKind + tags: tags + properties: { + displayName: displayName + customParameterValues: customParameterValues + parameterValueType: !empty(parameterValueType) ? parameterValueType : null + alternativeParameterValues: !empty(alternativeParameterValues) ? alternativeParameterValues : null + api: connectionApi + parameterValues: empty(alternativeParameterValues) ? parameterValues : null + nonSecretParameterValues: !empty(nonSecretParameterValues) ? nonSecretParameterValues : null + testLinks: !empty(testLinks) ? testLinks : null + statuses: !empty(statuses) ? statuses : null + } +} + +resource connection_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${connection.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: connection +} + +module connection_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Connection-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: connection.id + } +}] + +@description('The resource ID of the connection') +output resourceId string = connection.id + +@description('The resource group the connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the connection') +output name string = connection.name diff --git a/carml/1.0.0/Microsoft.Web/connections/readme.md b/carml/1.0.0/Microsoft.Web/connections/readme.md new file mode 100644 index 000000000..929389301 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/connections/readme.md @@ -0,0 +1,136 @@ +# API Connections `[Microsoft.Web/connections]` + +This module deploys an Azure API connection. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Web/connections` | 2016-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `alternativeParameterValues` | object | `{object}` | | Optional. Alternative parameter values. | +| `connectionApi` | object | `{object}` | | Optional. Specific values for some API connections. | +| `connectionKind` | string | | | Required. Connection Kind. Example: 'V1' when using blobs. It can change depending on the resource. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `customParameterValues` | object | `{object}` | | Optional. Customized parameter values for specific connections. | +| `displayName` | string | | | Required. Display name connection. Example: 'blobconnection' when using blobs. It can change depending on the resource. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location of the deployment. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `name` | string | | | Required. Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. | +| `nonSecretParameterValues` | object | `{object}` | | Optional. Dictionary of nonsecret parameter values. | +| `parameterValues` | secureObject | `{object}` | | Optional. Connection strings or access keys for connection. Example: 'accountName' and 'accessKey' when using blobs. It can change depending on the resource. | +| `parameterValueType` | string | | | Optional. Value Type of parameter, in case alternativeParameterValues is used. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `statuses` | array | `[]` | | Optional. Status of the connection. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `testLinks` | array | `[]` | | Optional. Links to test the API connection. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `connectionApi` + +```json +"connectionApi": { + "value": { + "id": "string", + "type": "string", + "swagger": {}, + "brandColor": "string", + "description": "string", + "displayName": "string", + "iconUri": "string", + "name": "string" + } +} +``` + +### Parameter Usage: `statuses` + +```json +"statuses": { + "value": [ + { + "status": "string", + "target": "string", + "error": { + "location": "string", + "tags": {}, + "properties": { + "code": "string", + "message": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `testLinks` + +```json +"testLinks": { + "value":[ + { + "requestUri": "string", + "method": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the connection | +| `resourceGroupName` | string | The resource group the connection was deployed into | +| `resourceId` | string | The resource ID of the connection | + +## Template references + +- [Connections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2016-06-01/connections) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Web/connections/version.json b/carml/1.0.0/Microsoft.Web/connections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/connections/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/carml/1.0.0/Microsoft.Web/hostingEnvironments/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Web/hostingEnvironments/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/hostingEnvironments/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Web/hostingEnvironments/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Web/hostingEnvironments/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..693168028 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/hostingEnvironments/.bicep/nested_rbac.bicep @@ -0,0 +1,33 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') +} + +resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2021-02-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appServiceEnvironment.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: appServiceEnvironment +}] diff --git a/carml/1.0.0/Microsoft.Web/hostingEnvironments/.parameters/parameters.json b/carml/1.0.0/Microsoft.Web/hostingEnvironments/.parameters/parameters.json new file mode 100644 index 000000000..cce2a3631 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/hostingEnvironments/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-appse-x-001" + }, + "subnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-006" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/hostingEnvironments/deploy.bicep b/carml/1.0.0/Microsoft.Web/hostingEnvironments/deploy.bicep new file mode 100644 index 000000000..a72da47c3 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/hostingEnvironments/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. Name of the App Service Environment') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Kind of resource.') +param kind string = 'ASEV2' + +@description('Required. ResourceId for the sub net') +param subnetResourceId string + +@description('Optional. Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing') +@allowed([ + 'None' + 'Web' + 'Publishing' +]) +param internalLoadBalancingMode string = 'None' + +@description('Optional. Frontend VM size, e.g. Medium, Large') +@allowed([ + 'Medium' + 'Large' + 'ExtraLarge' + 'Standard_D2' + 'Standard_D3' + 'Standard_D4' + 'Standard_D1_V2' + 'Standard_D2_V2' + 'Standard_D3_V2' + 'Standard_D4_V2' +]) +param multiSize string = 'Standard_D1_V2' + +@description('Optional. Number of frontend instances.') +param multiRoleCount int = 2 + +@description('Optional. Number of IP SSL addresses reserved for the App Service Environment.') +param ipsslAddressCount int = 2 + +@description('Optional. Description of worker pools with worker size IDs, VM sizes, and number of workers in each pool..') +param workerPools array = [] + +@description('Optional. DNS suffix of the App Service Environment.') +param dnsSuffix string = '' + +@description('Optional. Access control list for controlling traffic to the App Service Environment..') +param networkAccessControlList array = [] + +@description('Optional. Scale factor for frontends.') +param frontEndScaleFactor int = 15 + +@description('Optional. API Management Account associated with the App Service Environment.') +param apiManagementAccountId string = '' + +@description('Optional. true if the App Service Environment is suspended; otherwise, false. The environment can be suspended, e.g. when the management endpoint is no longer available (most likely because NSG blocked the incoming traffic).') +param suspended bool = false + +@description('Optional. True/false indicating whether the App Service Environment is suspended. The environment can be suspended e.g. when the management endpoint is no longer available(most likely because NSG blocked the incoming traffic).') +param dynamicCacheEnabled bool = false + +@description('Optional. User added ip ranges to whitelist on ASE db - string') +param userWhitelistedIpRanges array = [] + +@description('Optional. Flag that displays whether an ASE has linux workers or not') +param hasLinuxWorkers bool = false + +@description('Optional. Custom settings for changing the behavior of the App Service Environment') +param clusterSettings array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AppServiceEnvironmentPlatformLogs' +]) +param logsToEnable array = [ + 'AppServiceEnvironmentPlatformLogs' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var vnetResourceId = split(subnetResourceId, '/') + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2021-02-01' = { + name: name + kind: kind + location: location + tags: tags + properties: { + name: name + location: location + virtualNetwork: { + id: subnetResourceId + subnet: last(vnetResourceId) + } + internalLoadBalancingMode: internalLoadBalancingMode + multiSize: multiSize + multiRoleCount: multiRoleCount + workerPools: workerPools + ipsslAddressCount: ipsslAddressCount + dnsSuffix: dnsSuffix + networkAccessControlList: networkAccessControlList + frontEndScaleFactor: frontEndScaleFactor + apiManagementAccountId: apiManagementAccountId + suspended: suspended + dynamicCacheEnabled: dynamicCacheEnabled + clusterSettings: clusterSettings + userWhitelistedIpRanges: userWhitelistedIpRanges + hasLinuxWorkers: hasLinuxWorkers + } +} + +resource appServiceEnvironment_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appServiceEnvironment.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appServiceEnvironment +} + +resource appServiceEnvironment_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${appServiceEnvironment.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: appServiceEnvironment +} + +module appServiceEnvironment_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppServiceEnv-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appServiceEnvironment.id + } +}] + +@description('The resource ID of the app service environment') +output resourceId string = appServiceEnvironment.id + +@description('The resource group the app service environment was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the app service environment') +output name string = appServiceEnvironment.name diff --git a/carml/1.0.0/Microsoft.Web/hostingEnvironments/readme.md b/carml/1.0.0/Microsoft.Web/hostingEnvironments/readme.md new file mode 100644 index 000000000..fc7b8ee96 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/hostingEnvironments/readme.md @@ -0,0 +1,147 @@ +# App Service Environments `[Microsoft.Web/hostingEnvironments]` + +This module deploys an app service environment. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Web/hostingEnvironments` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementAccountId` | string | | | Optional. API Management Account associated with the App Service Environment. | +| `clusterSettings` | array | `[]` | | Optional. Custom settings for changing the behavior of the App Service Environment | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `dnsSuffix` | string | | | Optional. DNS suffix of the App Service Environment. | +| `dynamicCacheEnabled` | bool | | | Optional. True/false indicating whether the App Service Environment is suspended. The environment can be suspended e.g. when the management endpoint is no longer available(most likely because NSG blocked the incoming traffic). | +| `frontEndScaleFactor` | int | `15` | | Optional. Scale factor for frontends. | +| `hasLinuxWorkers` | bool | | | Optional. Flag that displays whether an ASE has linux workers or not | +| `internalLoadBalancingMode` | string | `None` | `[None, Web, Publishing]` | Optional. Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing | +| `ipsslAddressCount` | int | `2` | | Optional. Number of IP SSL addresses reserved for the App Service Environment. | +| `kind` | string | `ASEV2` | | Optional. Kind of resource. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[AppServiceEnvironmentPlatformLogs]` | `[AppServiceEnvironmentPlatformLogs]` | Optional. The name of logs that will be streamed. | +| `multiRoleCount` | int | `2` | | Optional. Number of frontend instances. | +| `multiSize` | string | `Standard_D1_V2` | `[Medium, Large, ExtraLarge, Standard_D2, Standard_D3, Standard_D4, Standard_D1_V2, Standard_D2_V2, Standard_D3_V2, Standard_D4_V2]` | Optional. Frontend VM size, e.g. Medium, Large | +| `name` | string | | | Required. Name of the App Service Environment | +| `networkAccessControlList` | array | `[]` | | Optional. Access control list for controlling traffic to the App Service Environment.. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `subnetResourceId` | string | | | Required. ResourceId for the sub net | +| `suspended` | bool | | | Optional. true if the App Service Environment is suspended; otherwise, false. The environment can be suspended, e.g. when the management endpoint is no longer available (most likely because NSG blocked the incoming traffic). | +| `tags` | object | `{object}` | | Optional. Resource tags. | +| `userWhitelistedIpRanges` | array | `[]` | | Optional. User added ip ranges to whitelist on ASE db - string | +| `workerPools` | array | `[]` | | Optional. Description of worker pools with worker size IDs, VM sizes, and number of workers in each pool.. | + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `workerPools` + +```json +"workerPools": { + "value": { + "workerPools": [ + { + "workerSizeId": 0, + "workerSize": "Small", + "workerCount": 2 + }, + { + "workerSizeId": 1, + "workerSize": "Small", + "workerCount": 2 + } + ] + } +} +``` + +workerPools can have two properties workerSize and workerCount: + +```json + "workerSize": { + "type": "string", + "allowedValues": [ + "Small", + "Medium", + "Large", + "ExtraLarge" + ], + "defaultValue": "Small", + "metadata": { + "description": "Instance size for worker pool one. Maps to P1,P2,P3,P4." + } + }, + "workerCount": { + "type": "int", + "defaultValue": 2, + "minValue": 2, + "maxValue": 100, + "metadata": { + "description": "Number of instances in worker pool one. Minimum of two." + } + } +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the app service environment | +| `resourceGroupName` | string | The resource group the app service environment was deployed into | +| `resourceId` | string | The resource ID of the app service environment | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Hostingenvironments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-02-01/hostingEnvironments) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.0/Microsoft.Web/hostingEnvironments/version.json b/carml/1.0.0/Microsoft.Web/hostingEnvironments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/hostingEnvironments/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/carml/1.0.0/Microsoft.Web/serverfarms/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Web/serverfarms/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/serverfarms/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Web/serverfarms/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Web/serverfarms/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e9946e974 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/serverfarms/.bicep/nested_rbac.bicep @@ -0,0 +1,36 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') +} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appServicePlan.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: appServicePlan +}] diff --git a/carml/1.0.0/Microsoft.Web/serverfarms/.parameters/parameters.json b/carml/1.0.0/Microsoft.Web/serverfarms/.parameters/parameters.json new file mode 100644 index 000000000..a778406fe --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/serverfarms/.parameters/parameters.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-asp-x-001" + }, + "sku": { + "value": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": "1" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/serverfarms/deploy.bicep b/carml/1.0.0/Microsoft.Web/serverfarms/deploy.bicep new file mode 100644 index 000000000..a1a995852 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/serverfarms/deploy.bicep @@ -0,0 +1,110 @@ +@description('Required. The name of the app service plan to deploy.') +@minLength(1) +@maxLength(40) +param name string + +@description('Required. Defines the name, tier, size, family and capacity of the App Service Plan.') +param sku object + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Kind of server OS.') +@allowed([ + 'Windows' + 'Linux' +]) +param serverOS string = 'Windows' + +@description('Optional. The Resource ID of the App Service Environment to use for the App Service Plan.') +param appServiceEnvironmentId string = '' + +@description('Optional. Target worker tier assigned to the App Service plan.') +param workerTierName string = '' + +@description('Optional. If true, apps assigned to this App Service plan can be scaled independently. If false, apps assigned to this App Service plan will scale to all instances of the plan.') +param perSiteScaling bool = false + +@description('Optional. Maximum number of total workers allowed for this ElasticScaleEnabled App Service Plan.') +param maximumElasticWorkerCount int = 1 + +@description('Optional. Scaling worker count.') +param targetWorkerCount int = 0 + +@description('Optional. The instance size of the hosting plan (small, medium, or large).') +@allowed([ + 0 + 1 + 2 +]) +param targetWorkerSize int = 0 + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var hostingEnvironmentProfile = { + id: appServiceEnvironmentId +} + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = { + name: name + kind: serverOS == 'Windows' ? '' : 'linux' + location: location + tags: tags + sku: sku + properties: { + workerTierName: workerTierName + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? hostingEnvironmentProfile : null + perSiteScaling: perSiteScaling + maximumElasticWorkerCount: maximumElasticWorkerCount + reserved: serverOS == 'Linux' + targetWorkerCount: targetWorkerCount + targetWorkerSizeId: targetWorkerSize + } +} + +resource appServicePlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appServicePlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appServicePlan +} + +module appServicePlan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppServicePlan-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appServicePlan.id + } +}] + +@description('The resource group the app service plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the app service plan') +output name string = appServicePlan.name + +@description('The resource ID of the app service plan') +output resourceId string = appServicePlan.id diff --git a/carml/1.0.0/Microsoft.Web/serverfarms/readme.md b/carml/1.0.0/Microsoft.Web/serverfarms/readme.md new file mode 100644 index 000000000..784b15dcd --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/serverfarms/readme.md @@ -0,0 +1,97 @@ +# App Service Plans `[Microsoft.Web/serverfarms]` + +This module deploys an app service plan. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Web/serverfarms` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appServiceEnvironmentId` | string | | | Optional. The Resource ID of the App Service Environment to use for the App Service Plan. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `maximumElasticWorkerCount` | int | `1` | | Optional. Maximum number of total workers allowed for this ElasticScaleEnabled App Service Plan. | +| `name` | string | | | Required. The name of the app service plan to deploy. | +| `perSiteScaling` | bool | | | Optional. If true, apps assigned to this App Service plan can be scaled independently. If false, apps assigned to this App Service plan will scale to all instances of the plan. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serverOS` | string | `Windows` | `[Windows, Linux]` | Optional. Kind of server OS. | +| `sku` | object | | | Required. Defines the name, tier, size, family and capacity of the App Service Plan. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `targetWorkerCount` | int | | | Optional. Scaling worker count. | +| `targetWorkerSize` | int | | `[0, 1, 2]` | Optional. The instance size of the hosting plan (small, medium, or large). | +| `workerTierName` | string | | | Optional. Target worker tier assigned to the App Service plan. | + +### Parameter Usage: `sku` + +```json +"sku": { + "value": { + "name": "P1v2", + "tier": "PremiumV2", + "size": "P1v2", + "family": "Pv2", + "capacity": 1 + } +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the app service plan | +| `resourceGroupName` | string | The resource group the app service plan was deployed into | +| `resourceId` | string | The resource ID of the app service plan | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Serverfarms](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-02-01/serverfarms) diff --git a/carml/1.0.0/Microsoft.Web/serverfarms/version.json b/carml/1.0.0/Microsoft.Web/serverfarms/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/serverfarms/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/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_components.bicep b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_components.bicep new file mode 100644 index 000000000..d9e7a6c98 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_components.bicep @@ -0,0 +1,81 @@ +@description('Required. Name of the application insights.') +param name string + +@description('Optional. Application type.') +@allowed([ + 'web' + 'other' +]) +param appInsightsType string = 'web' + +@description('Optional. Describes what tool created this app insights component. Customers using this API should set this to the default rest.') +@allowed([ + 'rest' +]) +param appInsightsRequestSource string = 'rest' + +@description('Required. Resource ID of the log analytics workspace which the data will be ingested to. This property is required to create an application with this API version. Applications from older versions will not have this property.') +param workspaceResourceId string + +@description('Optional. The network access type for accessing Application Insights ingestion. - Enabled or Disabled.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Optional. The network access type for accessing Application Insights query. - Enabled or Disabled.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Optional. The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone.') +param kind string = '' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +resource appInsights 'Microsoft.Insights/components@2020-02-02' = { + name: name + location: location + tags: tags + kind: kind + properties: { + Application_Type: appInsightsType + Request_Source: appInsightsRequestSource + WorkspaceResourceId: workspaceResourceId + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + } +} + +resource appInsights_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appInsights.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appInsights +} + +@description('The name of the application insights component.') +output name string = appInsights.name + +@description('The resource ID of the application insights component.') +output resourceId string = appInsights.id + +@description('The resource group the application insights component was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_privateEndpoint.bicep b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..517bc6038 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpointObj, 'name') ? (!empty(privateEndpointObj.name) ? privateEndpointObj.name : '${privateEndpointResourceName}-${privateEndpointObj.service}') : '${privateEndpointResourceName}-${privateEndpointObj.service}' + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (!empty(privateEndpointObj.privateDnsZoneResourceIds) ? privateEndpointObj.privateDnsZoneResourceIds : []) : [] + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (!empty(privateEndpointObj.customDnsConfigs) ? privateEndpointObj.customDnsConfigs : null) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_rbac.bicep b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..759726e64 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') +} + +resource app 'Microsoft.Web/sites@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(app.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: app +}] diff --git a/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_serverfarms.bicep b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_serverfarms.bicep new file mode 100644 index 000000000..06d715a52 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.bicep/nested_serverfarms.bicep @@ -0,0 +1,88 @@ +@description('Required. The name of the app service plan to deploy.') +@minLength(1) +@maxLength(40) +param name string + +@description('Required. Defines the name, tier, size, family and capacity of the app service plan.') +param sku object + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Kind of server OS.') +@allowed([ + 'Windows' + 'Linux' +]) +param serverOS string = 'Windows' + +@description('Optional. The resource ID of the app service environment to use for this resource.') +param appServiceEnvironmentId string = '' + +@description('Optional. Target worker tier assigned to the app service plan.') +param workerTierName string = '' + +@description('Optional. If true, apps assigned to this app service plan can be scaled independently. If false, apps assigned to this app service plan will scale to all instances of the plan.') +param perSiteScaling bool = false + +@description('Optional. Maximum number of total workers allowed for this ElasticScaleEnabled app service plan.') +param maximumElasticWorkerCount int = 1 + +@description('Optional. Scaling worker count.') +param targetWorkerCount int = 0 + +@description('Optional. The instance size of the hosting plan (small, medium, or large).') +@allowed([ + 0 + 1 + 2 +]) +param targetWorkerSize int = 0 + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = { + name: name + kind: serverOS == 'Windows' ? '' : 'linux' + location: location + tags: tags + sku: sku + properties: { + workerTierName: workerTierName + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? { + id: appServiceEnvironmentId + } : null + perSiteScaling: perSiteScaling + maximumElasticWorkerCount: maximumElasticWorkerCount + reserved: serverOS == 'Linux' + targetWorkerCount: targetWorkerCount + targetWorkerSizeId: targetWorkerSize + } +} + +resource appServicePlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appServicePlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appServicePlan +} + +@description('The name of the app service plan.') +output name string = appServicePlan.name + +@description('The resource ID of the app service plan.') +output resourceId string = appServicePlan.id + +@description('The resource group the app service plan was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Web/sites/.parameters/fa.min.parameters.json b/carml/1.0.0/Microsoft.Web/sites/.parameters/fa.min.parameters.json new file mode 100644 index 000000000..4fe2c2d5e --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.parameters/fa.min.parameters.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fa-min-001" + }, + "kind": { + "value": "functionapp" + }, + "appServicePlanObject": { + "value": { + "serverOS": "Linux", + "skuName": "P1v2", + "skuCapacity": 2, + "skuTier": "PremiumV2", + "skuSize": "P1v2", + "skuFamily": "Pv2" + } + }, + "siteConfig": { + "value": { + "alwaysOn": true + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/sites/.parameters/fa.parameters.json b/carml/1.0.0/Microsoft.Web/sites/.parameters/fa.parameters.json new file mode 100644 index 000000000..4859115bd --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.parameters/fa.parameters.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fa-x-001" + }, + "kind": { + "value": "functionapp" + }, + "appServicePlanObject": { + "value": { + "name": "<>-az-fa-x-001-asp", + "serverOS": "Linux", + "skuName": "P1v2", + "skuCapacity": 2, + "skuTier": "PremiumV2", + "skuSize": "P1v2", + "skuFamily": "Pv2" + } + }, + "appInsightId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001" + }, + "siteConfig": { + "value": { + "alwaysOn": true + } + }, + "storageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsafa001" + }, + "functionsWorkerRuntime": { + "value": "powershell" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/sites/.parameters/wa.min.parameters.json b/carml/1.0.0/Microsoft.Web/sites/.parameters/wa.min.parameters.json new file mode 100644 index 000000000..c30d3d278 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.parameters/wa.min.parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-wa-min-001" + }, + "kind": { + "value": "app" + }, + "appServicePlanObject": { + "value": { + "serverOS": "Linux", + "skuName": "P1v2", + "skuCapacity": 2, + "skuTier": "PremiumV2", + "skuSize": "P1v2", + "skuFamily": "Pv2" + } + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/sites/.parameters/wa.parameters.json b/carml/1.0.0/Microsoft.Web/sites/.parameters/wa.parameters.json new file mode 100644 index 000000000..31b54a731 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/.parameters/wa.parameters.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-wa-x-001" + }, + "kind": { + "value": "app" + }, + "appServicePlanObject": { + "value": { + "name": "<>-az-wa-x-001-asp", + "serverOS": "Linux", + "skuName": "P1v2", + "skuCapacity": 2, + "skuTier": "PremiumV2", + "skuSize": "P1v2", + "skuFamily": "Pv2" + } + }, + "appInsightObject": { + "value": { + "name": "<>-az-wa-x-001-appi", + "workspaceResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.OperationalInsights/workspaces/adp-<>-az-law-appi-001" + } + }, + "siteConfig": { + "value": { + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ], + "alwaysOn": true + } + }, + "httpsOnly": { + "value": true + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.0/Microsoft.Web/sites/config/.bicep/nested_cuaId.bicep b/carml/1.0.0/Microsoft.Web/sites/config/.bicep/nested_cuaId.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/carml/1.0.0/Microsoft.Web/sites/config/deploy.bicep b/carml/1.0.0/Microsoft.Web/sites/config/deploy.bicep new file mode 100644 index 000000000..5f04f840a --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/config/deploy.bicep @@ -0,0 +1,72 @@ +@description('Required. Name of the site config.') +@allowed([ + 'appsettings' +]) +param name string + +@description('Required. Name of the site parent resource.') +param appName string + +@description('Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions.') +param storageAccountId string = '' + +@description('Optional. Runtime of the function worker.') +@allowed([ + 'dotnet' + 'node' + 'python' + 'java' + 'powershell' + '' +]) +param functionsWorkerRuntime string = '' + +@description('Optional. Version of the function extension.') +param functionsExtensionVersion string = '~3' + +@description('Optional. Resource ID of the app insight to leverage for this resource.') +param appInsightId string = '' + +@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 appInsight 'microsoft.insights/components@2020-02-02' existing = if (!empty(appInsightId)) { + name: last(split(appInsightId, '/')) + scope: resourceGroup(split(appInsightId, '/')[2], split(appInsightId, '/')[4]) +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' existing = if (!empty(storageAccountId)) { + name: last(split(storageAccountId, '/')) + scope: resourceGroup(split(storageAccountId, '/')[2], split(storageAccountId, '/')[4]) +} + +resource app 'Microsoft.Web/sites@2020-12-01' existing = { + name: appName +} + +resource config 'Microsoft.Web/sites/config@2021-02-01' = { + name: name + parent: app + properties: { + AzureWebJobsStorage: !empty(storageAccountId) ? 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' : any(null) + AzureWebJobsDashboard: !empty(storageAccountId) ? 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' : any(null) + FUNCTIONS_EXTENSION_VERSION: app.kind == 'functionapp' && !empty(functionsExtensionVersion) ? functionsExtensionVersion : any(null) + FUNCTIONS_WORKER_RUNTIME: app.kind == 'functionapp' && !empty(functionsWorkerRuntime) ? functionsWorkerRuntime : any(null) + APPINSIGHTS_INSTRUMENTATIONKEY: !empty(appInsightId) ? appInsight.properties.InstrumentationKey : '' + APPLICATIONINSIGHTS_CONNECTION_STRING: !empty(appInsightId) ? appInsight.properties.ConnectionString : '' + } +} + +@description('The name of the site config.') +output name string = config.name + +@description('The resource ID of the site config.') +output resourceId string = config.id + +@description('The resource group the site config was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.0/Microsoft.Web/sites/config/readme.md b/carml/1.0.0/Microsoft.Web/sites/config/readme.md new file mode 100644 index 000000000..612316619 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/config/readme.md @@ -0,0 +1,33 @@ +# Web Site Config `[Microsoft.Web/sites/config]` + +This module deploys a site config resource. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Web/sites/config` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appInsightId` | string | | | Optional. Resource ID of the app insight to leverage for this resource. | +| `appName` | string | | | Required. Name of the site parent resource. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `functionsExtensionVersion` | string | `~3` | | Optional. Version of the function extension. | +| `functionsWorkerRuntime` | string | | `[dotnet, node, python, java, powershell, ]` | Optional. Runtime of the function worker. | +| `name` | string | | `[appsettings]` | Required. Name of the site config. | +| `storageAccountId` | string | | | Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the site config. | +| `resourceGroupName` | string | The resource group the site config was deployed into. | +| `resourceId` | string | The resource ID of the site config. | + +## Template references + +- ['sites/config' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) diff --git a/carml/1.0.0/Microsoft.Web/sites/config/version.json b/carml/1.0.0/Microsoft.Web/sites/config/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/config/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/carml/1.0.0/Microsoft.Web/sites/deploy.bicep b/carml/1.0.0/Microsoft.Web/sites/deploy.bicep new file mode 100644 index 000000000..3f56a501a --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/deploy.bicep @@ -0,0 +1,270 @@ +@description('Required. Name of the site.') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Required. Type of site to deploy.') +@allowed([ + 'functionapp' + 'app' +]) +param kind string + +@description('Optional. Configures a site to accept only HTTPS requests. Issues redirect for HTTP requests.') +param httpsOnly bool = true + +@description('Optional. If client affinity is enabled.') +param clientAffinityEnabled bool = true + +@description('Optional. Configuration of the app.') +param siteConfig object = {} + +@description('Optional. Required if functionapp kind. The resource ID of the storage account to manage triggers and logging function executions.') +param storageAccountId string = '' + +@description('Optional. Runtime of the function worker.') +@allowed([ + 'dotnet' + 'node' + 'python' + 'java' + 'powershell' + '' +]) +param functionsWorkerRuntime string = '' + +@description('Optional. Version if the function extension.') +param functionsExtensionVersion string = '~3' + +@description('Optional. The resource ID of the app service plan to use for the site. If not provided, the appServicePlanObject is used to create a new plan.') +param appServicePlanId string = '' + +@description('Optional. Required if no appServicePlanId is provided to deploy a new app service plan.') +param appServicePlanObject object = {} + +@description('Optional. The resource ID of the existing app insight to leverage for the app. If the resource ID is not provided, the appInsightObject can be used to create a new app insight.') +param appInsightId string = '' + +@description('Optional. Used to deploy a new app insight if no appInsightId is provided.') +param appInsightObject object = {} + +@description('Optional. The resource ID of the app service environment to use for this resource.') +param appServiceEnvironmentId string = '' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Configuration details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AppServiceHTTPLogs' + 'AppServiceConsoleLogs' + 'AppServiceAppLogs' + 'AppServiceFileAuditLogs' + 'AppServiceAuditLogs' + 'FunctionAppLogs' +]) +param logsToEnable array = kind == 'functionapp' ? [ + 'FunctionAppLogs' +] : [ + 'AppServiceHTTPLogs' + 'AppServiceConsoleLogs' + 'AppServiceAppLogs' + 'AppServiceFileAuditLogs' + 'AppServiceAuditLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource appServicePlanExisting 'Microsoft.Web/serverfarms@2021-02-01' existing = if (!empty(appServicePlanId)) { + name: last(split(appServicePlanId, '/')) + scope: resourceGroup(split(appServicePlanId, '/')[2], split(appServicePlanId, '/')[4]) +} + +module appServicePlan '.bicep/nested_serverfarms.bicep' = if (empty(appServicePlanId)) { + name: '${uniqueString(deployment().name, location)}-Site-AppServicePlan' + params: { + name: contains(appServicePlanObject, 'name') ? !empty(appServicePlanObject.name) ? appServicePlanObject.name : '${name}-asp' : '${name}-asp' + location: location + tags: tags + serverOS: appServicePlanObject.serverOS + sku: { + name: appServicePlanObject.skuName + capacity: appServicePlanObject.skuCapacity + tier: appServicePlanObject.skuTier + size: appServicePlanObject.skuSize + family: appServicePlanObject.skuFamily + } + appServiceEnvironmentId: appServiceEnvironmentId + lock: lock + } +} + +module appInsight '.bicep/nested_components.bicep' = if (!empty(appInsightObject)) { + name: '${uniqueString(deployment().name, location)}-Site-AppInsight' + params: { + name: contains(appInsightObject, 'name') ? !empty(appInsightObject.name) ? appInsightObject.name : '${name}-appi' : '${name}-appi' + workspaceResourceId: appInsightObject.workspaceResourceId + tags: tags + lock: lock + } +} + +resource app 'Microsoft.Web/sites@2020-12-01' = { + name: name + location: location + kind: kind + tags: tags + identity: identity + properties: { + serverFarmId: !empty(appServicePlanId) ? appServicePlanExisting.id : appServicePlan.outputs.resourceId + httpsOnly: httpsOnly + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? { + id: appServiceEnvironmentId + } : null + clientAffinityEnabled: clientAffinityEnabled + siteConfig: siteConfig + } +} + +module app_appsettings 'config/deploy.bicep' = { + name: '${uniqueString(deployment().name, location)}-Site-Config' + params: { + name: 'appsettings' + appName: app.name + storageAccountId: !empty(storageAccountId) ? storageAccountId : '' + appInsightId: !empty(appInsightId) ? appInsightId : !empty(appInsightObject) ? appInsight.outputs.resourceId : '' + functionsWorkerRuntime: !empty(functionsWorkerRuntime) ? functionsWorkerRuntime : '' + functionsExtensionVersion: !empty(functionsExtensionVersion) ? functionsExtensionVersion : '~3' + } +} + +resource app_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${app.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: app +} + +resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${app.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: app +} + +module app_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Site-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: app.id + } +}] + +module app_privateEndpoint '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-Site-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: app.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The name of the site.') +output name string = app.name + +@description('The resource ID of the site.') +output resourceId string = app.id + +@description('The resource group the site was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(app.identity, 'principalId') ? app.identity.principalId : '' diff --git a/carml/1.0.0/Microsoft.Web/sites/readme.md b/carml/1.0.0/Microsoft.Web/sites/readme.md new file mode 100644 index 000000000..65c3de17d --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/readme.md @@ -0,0 +1,195 @@ +# Web/Function Apps `[Microsoft.Web/sites]` + +This module deploys a web or function app. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/components` | 2020-02-02 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.Web/serverfarms` | 2021-02-01 | +| `Microsoft.Web/sites` | 2020-12-01 | +| `Microsoft.Web/sites/config` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appInsightId` | string | | | Optional. The resource ID of the existing app insight to leverage for the app. If the resource ID is not provided, the appInsightObject can be used to create a new app insight. | +| `appInsightObject` | object | `{object}` | | Optional. Used to deploy a new app insight if no appInsightId is provided. | +| `appServiceEnvironmentId` | string | | | Optional. The resource ID of the app service environment to use for this resource. | +| `appServicePlanId` | string | | | Optional. The resource ID of the app service plan to use for the site. If not provided, the appServicePlanObject is used to create a new plan. | +| `appServicePlanObject` | object | `{object}` | | Optional. Required if no appServicePlanId is provided to deploy a new app service plan. | +| `clientAffinityEnabled` | bool | `True` | | Optional. If client affinity is enabled. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `diagnosticEventHubAuthorizationRuleId` | string | | | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | | | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of log analytics workspace. | +| `functionsExtensionVersion` | string | `~3` | | Optional. Version if the function extension. | +| `functionsWorkerRuntime` | string | | `[dotnet, node, python, java, powershell, ]` | Optional. Runtime of the function worker. | +| `httpsOnly` | bool | `True` | | Optional. Configures a site to accept only HTTPS requests. Issues redirect for HTTP requests. | +| `kind` | string | | `[functionapp, app]` | Required. Type of site to deploy. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[if(equals(parameters('kind'), 'functionapp'), createArray('FunctionAppLogs'), createArray('AppServiceHTTPLogs', 'AppServiceConsoleLogs', 'AppServiceAppLogs', 'AppServiceFileAuditLogs', 'AppServiceAuditLogs'))]` | `[AppServiceHTTPLogs, AppServiceConsoleLogs, AppServiceAppLogs, AppServiceFileAuditLogs, AppServiceAuditLogs, FunctionAppLogs]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. Name of the site. | +| `privateEndpoints` | array | `[]` | | Optional. Configuration details for private endpoints. | +| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `siteConfig` | object | `{object}` | | Optional. Configuration of the app. | +| `storageAccountId` | string | | | Optional. Required if functionapp kind. The resource ID of the storage account to manage triggers and logging function executions. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the site. | +| `resourceGroupName` | string | The resource group the site was deployed into. | +| `resourceId` | string | The resource ID of the site. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- ['sites/config' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) +- [Components](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2020-02-02/components) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-03-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Serverfarms](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-02-01/serverfarms) +- [Sites](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2020-12-01/sites) diff --git a/carml/1.0.0/Microsoft.Web/sites/version.json b/carml/1.0.0/Microsoft.Web/sites/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.0/Microsoft.Web/sites/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/carml/1.0.0/README.md b/carml/1.0.0/README.md new file mode 100644 index 000000000..0f9ba243b --- /dev/null +++ b/carml/1.0.0/README.md @@ -0,0 +1,94 @@ +In this section you can find useful information regarding the Modules that are contained in this repository. + +## Available Resource Modules + +| Name | Provider namespace | Resource Type | +| - | - | - | +| [Analysis Services Server](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AnalysisServices/servers) | `MS.AnalysisServices` | [servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AnalysisServices/servers) | +| [API Management Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ApiManagement/service) | `MS.ApiManagement` | [service](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ApiManagement/service) | +| [Policy Assignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyAssignments) | `MS.Authorization` | [policyAssignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyAssignments) | +| [Policy Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyDefinitions) | | [policyDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyDefinitions) | +| [Policy Exemptions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyExemptions) | | [policyExemptions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyExemptions) | +| [Policy Set Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policySetDefinitions) | | [policySetDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policySetDefinitions) | +| [Role Assignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleAssignments) | | [roleAssignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleAssignments) | +| [Role Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleDefinitions) | | [roleDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleDefinitions) | +| [Automation Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Automation/automationAccounts) | `MS.Automation` | [automationAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Automation/automationAccounts) | +| [Batch Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Batch/batchAccounts) | `MS.Batch` | [batchAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Batch/batchAccounts) | +| [Cognitive Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.CognitiveServices/accounts) | `MS.CognitiveServices` | [accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.CognitiveServices/accounts) | +| [Availability Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/availabilitySets) | `MS.Compute` | [availabilitySets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/availabilitySets) | +| [Disk Encryption Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/diskEncryptionSets) | | [diskEncryptionSets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/diskEncryptionSets) | +| [Compute Disks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/disks) | | [disks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/disks) | +| [Azure Compute Galleries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/galleries) | | [galleries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/galleries) | +| [Images](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/images) | | [images](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/images) | +| [Proximity Placement Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/proximityPlacementGroups) | | [proximityPlacementGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/proximityPlacementGroups) | +| [Virtual Machines](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachines) | | [virtualMachines](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachines) | +| [Virtual Machine Scale Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachineScaleSets) | | [virtualMachineScaleSets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachineScaleSets) | +| [Budgets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Consumption/budgets) | `MS.Consumption` | [budgets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Consumption/budgets) | +| [Container Instances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerInstance/containerGroups) | `MS.ContainerInstance` | [containerGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerInstance/containerGroups) | +| [Container Registries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerRegistry/registries) | `MS.ContainerRegistry` | [registries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerRegistry/registries) | +| [Azure Kubernetes Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerService/managedClusters) | `MS.ContainerService` | [managedClusters](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerService/managedClusters) | +| [Azure Databricks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Databricks/workspaces) | `MS.Databricks` | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Databricks/workspaces) | +| [Data Factories](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DataFactory/factories) | `MS.DataFactory` | [factories](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DataFactory/factories) | +| [AVD Application Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/applicationgroups) | `MS.DesktopVirtualization` | [applicationgroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/applicationgroups) | +| [AVD Host Pools](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/hostpools) | | [hostpools](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/hostpools) | +| [AVD Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/workspaces) | | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/workspaces) | +| [DocumentDB Database Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DocumentDB/databaseAccounts) | `MS.DocumentDB` | [databaseAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DocumentDB/databaseAccounts) | +| [Event Grid Topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/systemTopics) | `MS.EventGrid` | [systemTopics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/systemTopics) | +| [Event Grid Topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/topics) | | [topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/topics) | +| [Event Hub Namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventHub/namespaces) | `MS.EventHub` | [namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventHub/namespaces) | +| [Azure Health Bots](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.HealthBot/healthBots) | `MS.HealthBot` | [healthBots](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.HealthBot/healthBots) | +| [Action Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/actionGroups) | `MS.Insights` | [actionGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/actionGroups) | +| [Activity Log Alerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/activityLogAlerts) | | [activityLogAlerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/activityLogAlerts) | +| [Application Insights](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/components) | | [components](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/components) | +| [Activity Logs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/diagnosticSettings) | | [diagnosticSettings](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/diagnosticSettings) | +| [Metric Alerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/metricAlerts) | | [metricAlerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/metricAlerts) | +| [Azure Monitor Private Link Scopes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/privateLinkScopes) | | [privateLinkScopes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/privateLinkScopes) | +| [Scheduled Query Rules](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/scheduledQueryRules) | | [scheduledQueryRules](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/scheduledQueryRules) | +| [Key Vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KeyVault/vaults) | `MS.KeyVault` | [vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KeyVault/vaults) | +| [Logic Apps](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Logic/workflows) | `MS.Logic` | [workflows](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Logic/workflows) | +| [Machine Learning Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.MachineLearningServices/workspaces) | `MS.achineLearningServices` | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.MachineLearningServices/workspaces) | +| [User Assigned Identities](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedIdentity/userAssignedIdentities) | `MS.anagedIdentity` | [userAssignedIdentities](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedIdentity/userAssignedIdentities) | +| [Registration Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedServices/registrationDefinitions) | `MS.anagedServices` | [registrationDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedServices/registrationDefinitions) | +| [Management Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Management/managementGroups) | `MS.anagement` | [managementGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Management/managementGroups) | +| [Azure NetApp Files](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.NetApp/netAppAccounts) | `MS.NetApp` | [netAppAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.NetApp/netAppAccounts) | +| [Network Application Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationGateways) | `MS.Network` | [applicationGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationGateways) | +| [Application Security Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationSecurityGroups) | | [applicationSecurityGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationSecurityGroups) | +| [Azure Firewalls](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/azureFirewalls) | | [azureFirewalls](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/azureFirewalls) | +| [Bastion Hosts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/bastionHosts) | | [bastionHosts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/bastionHosts) | +| [Virtual Network Gateway Connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/connections) | | [connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/connections) | +| [DDoS Protection Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ddosProtectionPlans) | | [ddosProtectionPlans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ddosProtectionPlans) | +| [ExpressRoute Circuits](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/expressRouteCircuits) | | [expressRouteCircuits](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/expressRouteCircuits) | +| [Network Firewall Policies](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/firewallPolicies) | | [firewallPolicies](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/firewallPolicies) | +| [IP Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ipGroups) | | [ipGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ipGroups) | +| [Load Balancers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/loadBalancers) | | [loadBalancers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/loadBalancers) | +| [Local Network Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/localNetworkGateways) | | [localNetworkGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/localNetworkGateways) | +| [NAT Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/natGateways) | | [natGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/natGateways) | +| [Network Security Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkSecurityGroups) | | [networkSecurityGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkSecurityGroups) | +| [Network Watchers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkWatchers) | | [networkWatchers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkWatchers) | +| [Private DNS Zones](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateDnsZones) | | [privateDnsZones](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateDnsZones) | +| [Private Endpoints](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateEndpoints) | | [privateEndpoints](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateEndpoints) | +| [Public IP Addresses](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPAddresses) | | [publicIPAddresses](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPAddresses) | +| [Public IP Prefixes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPPrefixes) | | [publicIPPrefixes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPPrefixes) | +| [Route Tables](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/routeTables) | | [routeTables](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/routeTables) | +| [Traffic Manager Profiles](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/trafficmanagerprofiles) | | [trafficmanagerprofiles](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/trafficmanagerprofiles) | +| [Virtual Hub](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualHubs) | | [virtualHubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualHubs) | +| [Virtual Network Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworkGateways) | | [virtualNetworkGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworkGateways) | +| [Virtual Networks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworks) | | [virtualNetworks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworks) | +| [Virtual WANs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualWans) | | [virtualWans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualWans) | +| [Log Analytics Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.OperationalInsights/workspaces) | `MS.OperationalInsights` | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.OperationalInsights/workspaces) | +| [Recovery Services Vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.RecoveryServices/vaults) | `MS.RecoveryServices` | [vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.RecoveryServices/vaults) | +| [Deployment Scripts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/deploymentScripts) | `MS.Resources` | [deploymentScripts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/deploymentScripts) | +| [Resource Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/resourceGroups) | | [resourceGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/resourceGroups) | +| [Resources Tags](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/tags) | | [tags](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/tags) | +| [Azure Security Center](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Security/azureSecurityCenter) | `MS.Security` | [azureSecurityCenter](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Security/azureSecurityCenter) | +| [Service Bus Namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceBus/namespaces) | `MS.ServiceBus` | [namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceBus/namespaces) | +| [ServiceFabric Cluster](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceFabric/clusters) | `MS.ServiceFabric` | [clusters](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceFabric/clusters) | +| [SQL Managed Instances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/managedInstances) | `MS.Sql` | [managedInstances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/managedInstances) | +| [SQL Servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/servers) | | [servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/servers) | +| [Storage Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Storage/storageAccounts) | `MS.Storage` | [storageAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Storage/storageAccounts) | +| [Synapse PrivateLinkHubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Synapse/privateLinkHubs) | `MS.Synapse` | [privateLinkHubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Synapse/privateLinkHubs) | +| [Image Templates](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.VirtualMachineImages/imageTemplates) | `MS.VirtualMachineImages` | [imageTemplates](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.VirtualMachineImages/imageTemplates) | +| [API Connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/connections) | `MS.Web` | [connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/connections) | +| [App Service Environments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/hostingEnvironments) | | [hostingEnvironments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/hostingEnvironments) | +| [App Service Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/serverfarms) | | [serverfarms](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/serverfarms) | +| [Web/Function Apps](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/sites) | | [sites](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/sites) | diff --git a/carml/1.0.0/global.module.tests.ps1 b/carml/1.0.0/global.module.tests.ps1 new file mode 100644 index 000000000..2d44d67cb --- /dev/null +++ b/carml/1.0.0/global.module.tests.ps1 @@ -0,0 +1,875 @@ +#Requires -Version 7 + +param ( + [array] $moduleFolderPaths = ((Get-ChildItem (Split-Path $PSScriptRoot -Parent) -Recurse -Directory -Force).FullName | Where-Object { + (Get-ChildItem $_ -File -Depth 0 -Include @('deploy.json', 'deploy.bicep') -Force).Count -gt 0 + }) +) + +$script:Settings = Get-Content -Path (Join-Path $PSScriptRoot '..\..\settings.json') | ConvertFrom-Json +$script:RGdeployment = 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' +$script:Subscriptiondeployment = 'https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#' +$script:MGdeployment = 'https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#' +$script:Tenantdeployment = 'https://schema.management.azure.com/schemas/2019-08-01/tenantDeploymentTemplate.json#' +$script:moduleFolderPaths = $moduleFolderPaths +$script:moduleFolderPathsFiltered = $moduleFolderPaths | Where-Object { + (Split-Path $_ -Leaf) -notin @( 'AzureNetappFiles', 'TrafficManager', 'PrivateDnsZones', 'ManagementGroups') } + +# Import any helper function used in this test script +Import-Module (Join-Path $PSScriptRoot 'shared\helper.psm1') + +Describe 'File/folder tests' -Tag Modules { + + Context 'General module folder tests' { + + $moduleFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + $moduleFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + moduleFolderPath = $moduleFolderPath + } + } + + It '[] Module should contain a [deploy.json/deploy.bicep] file' -TestCases $moduleFolderTestCases { + param( [string] $moduleFolderPath ) + + $hasARM = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.json')) + $hasBicep = (Test-Path (Join-Path -Path $moduleFolderPath 'deploy.bicep')) + ($hasARM -or $hasBicep) | Should -Be $true + } + + It '[] Module should contain a [readme.md] file' -TestCases $moduleFolderTestCases { + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true + } + + It '[] Module should contain a [.parameters] folder' -TestCases $moduleFolderTestCases { + param( [string] $moduleFolderPath ) + if ((Split-Path (Split-Path $moduleFolderPath -Parent) -Leaf) -like 'Microsoft.*') { + (Test-Path (Join-Path -Path $moduleFolderPath '.parameters')) | Should -Be $true + } else { + $true | Should -Be $true + } + } + + It '[] Module should contain a [version.json] file' -TestCases $moduleFolderTestCases { + param( [string] $moduleFolderPath ) + (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true + } + } + + Context '.parameters folder' { + + $folderTestCases = [System.Collections.ArrayList]@() + foreach ($moduleFolderPath in $moduleFolderPaths) { + if (Test-Path (Join-Path $moduleFolderPath '.paramateres')) { + $folderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + moduleFolderPath = $moduleFolderPath + } + } + } + + It '[] folder should contain one or more *parameters.json files' -TestCases $folderTestCases { + param( + $moduleFolderName, + $moduleFolderPath + ) + $parameterFolderPath = Join-Path $moduleFolderPath '.parameters' + (Get-ChildItem $parameterFolderPath -Filter '*parameters.json' -Force).Count | Should -BeGreaterThan 0 + } + + $parameterFolderFilesTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + $parameterFolderPath = Join-Path $moduleFolderPath '.parameters' + if (Test-Path $parameterFolderPath) { + foreach ($parameterFile in (Get-ChildItem $parameterFolderPath -Filter '*parameters.json' -Force)) { + $parameterFolderFilesTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + parameterFilePath = $parameterFile.FullName + } + } + } + } + + It '[] *parameters.json files in the .parameters folder should be valid json' -TestCases $parameterFolderFilesTestCases { + param( + $moduleFolderName, + $parameterFilePath + ) + (Get-Content $parameterFilePath) | ConvertFrom-Json + } + } +} + +Describe 'Readme tests' -Tag Readme { + + Context 'Readme content tests' { + + $readmeFolderTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateContent = az bicep build --file (Join-Path $moduleFolderPath 'deploy.bicep') --stdout | ConvertFrom-Json -AsHashtable + } elseif (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateContent = Get-Content (Join-Path $moduleFolderPath 'deploy.json') -Raw | ConvertFrom-Json -AsHashtable + } else { + throw "No template file found in folder [$moduleFolderPath]" + } + + $readmeFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + moduleFolderPath = $moduleFolderPath + templateContent = $templateContent + readMeContent = Get-Content (Join-Path -Path $moduleFolderPath 'readme.md') + } + } + + It '[] Readme.md file should not be empty' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $readMeContent + ) + $readMeContent | Should -Not -Be $null + } + + It '[] Readme.md file should contain the these titles in order: Resource Types, Parameters, Outputs, Template references' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $readMeContent + ) + + $ReadmeHTML = ($readMeContent | ConvertFrom-Markdown -ErrorAction SilentlyContinue).Html + + $Heading2Order = @('Resource Types', 'parameters', 'Outputs', 'Template references') + $Headings2List = @() + foreach ($H in $ReadmeHTML) { + if ($H.Contains('') + 1 + $EndIndex = $H.LastIndexof('<') + $headings2List += ($H.Substring($StartingIndex, $EndIndex - $StartingIndex)) + } + } + + $differentiatingItems = $Heading2Order | Where-Object { $Headings2List -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of heading titles missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } + + It '[] Resources section should contain all resources from the template file' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $templateContent, + $readMeContent + ) + + # Get ReadMe data + $resourcesSectionStartIndex = 0 + while ($readMeContent[$resourcesSectionStartIndex] -notlike '*# Resource Types' -and -not ($resourcesSectionStartIndex -ge $readMeContent.count)) { + $resourcesSectionStartIndex++ + } + + $resourcesTableStartIndex = $resourcesSectionStartIndex + 1 + while ($readMeContent[$resourcesTableStartIndex] -notlike '*|*' -and -not ($resourcesTableStartIndex -ge $readMeContent.count)) { + $resourcesTableStartIndex++ + } + + $resourcesTableEndIndex = $resourcesTableStartIndex + 2 + while ($readMeContent[$resourcesTableEndIndex] -like '|*' -and -not ($resourcesTableEndIndex -ge $readMeContent.count)) { + $resourcesTableEndIndex++ + } + + $ReadMeResourcesList = [System.Collections.ArrayList]@() + for ($index = $resourcesTableStartIndex + 2; $index -lt $resourcesTableEndIndex; $index++) { + $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } + + # Get template data + $templateResources = (Get-NestedResourceList -TemplateContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique + + # Compare + $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ("list of template resources missing from the ReadMe's list [{0}] should be empty" -f ($differentiatingItems -join ',')) + } + + It '[] Resources section should not contain more resources as in the template file' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $templateContent, + $readMeContent + ) + + # Get ReadMe data + $resourcesSectionStartIndex = 0 + while ($readMeContent[$resourcesSectionStartIndex] -notlike '*# Resource Types' -and -not ($resourcesSectionStartIndex -ge $readMeContent.count)) { + $resourcesSectionStartIndex++ + } + + $resourcesTableStartIndex = $resourcesSectionStartIndex + 1 + while ($readMeContent[$resourcesTableStartIndex] -notlike '*|*' -and -not ($resourcesTableStartIndex -ge $readMeContent.count)) { + $resourcesTableStartIndex++ + } + + $resourcesTableEndIndex = $resourcesTableStartIndex + 2 + while ($readMeContent[$resourcesTableEndIndex] -like '|*' -and -not ($resourcesTableEndIndex -ge $readMeContent.count)) { + $resourcesTableEndIndex++ + } + + $ReadMeResourcesList = [System.Collections.ArrayList]@() + for ($index = $resourcesTableStartIndex + 2; $index -lt $resourcesTableEndIndex; $index++) { + $ReadMeResourcesList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } + + # Get template data + $templateResources = (Get-NestedResourceList -TemplateContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ }).type | Select-Object -Unique + + # Compare + $differentiatingItems = $templateResources | Where-Object { $ReadMeResourcesList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ("list of resources in the ReadMe's list [{0}] not in the template file should be empty" -f ($differentiatingItems -join ',')) + } + + It '[] parameters section should contain a table with these column names in order: Parameter Name, Type, Default Value, Possible values, Description' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $readMeContent + ) + + $ReadmeHTML = ($readMeContent | ConvertFrom-Markdown -ErrorAction SilentlyContinue).Html + $ParameterHeadingOrder = @('Parameter Name', 'Type', 'Default Value', 'Allowed Values', 'Description') + $ComparisonFlag = 0 + $Headings = @(@()) + foreach ($H in $ReadmeHTML) { + if ($H.Contains('') + 1 + $EndIndex = $H.LastIndexof('<') + $Headings += , (@($H.Substring($StartingIndex, $EndIndex - $StartingIndex), $ReadmeHTML.IndexOf($H))) + } + } + $HeadingIndex = $Headings | Where-Object { $_ -eq 'parameters' } + if ($HeadingIndex -eq $null) { + Write-Verbose "[parameters section should contain a table with these column names in order: Parameter Name, Type, Default Value, Possible values, Description] Error At ($moduleFolderName)" -Verbose + $true | Should -Be $false + } + $ParameterHeadingsList = $ReadmeHTML[$HeadingIndex[1] + 2].Replace('

|', '').Replace('|

', '').Split('|').Trim() + if (Compare-Object -ReferenceObject $ParameterHeadingOrder -DifferenceObject $ParameterHeadingsList -SyncWindow 0) { + $ComparisonFlag = $ComparisonFlag + 1 + } + ($ComparisonFlag -gt 2) | Should -Be $false + } + + It '[] parameters section should contain all parameters from the template file' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $templateContent, + $readMeContent + ) + + # Get Template data + $parameters = $templateContent.parameters.Keys + + # Get ReadMe data + $parametersSectionStartIndex = 0 + while ($readMeContent[$parametersSectionStartIndex] -notlike '*# Parameters' -and -not ($parametersSectionStartIndex -ge $readMeContent.count)) { + $parametersSectionStartIndex++ + } + + $parametersTableStartIndex = $parametersSectionStartIndex + 1 + while ($readMeContent[$parametersTableStartIndex] -notlike '*|*' -and -not ($parametersTableStartIndex -ge $readMeContent.count)) { + $parametersTableStartIndex++ + } + + if ($parametersSectionStartIndex -ge $readMeContent.count) { + throw 'Parameters section is missing in the Readme. Please add and re-run the tests.' + } + + $parametersTableEndIndex = $parametersTableStartIndex + 2 # Header row + table separator row + while ($readMeContent[$parametersTableEndIndex] -like '*|*' -and -not ($parametersTableEndIndex -ge $readMeContent.count)) { + $parametersTableEndIndex++ + } + $parametersTableEndIndex-- # remove one index as the while loop will move one index past the last table row + + $parametersList = [System.Collections.ArrayList]@() + for ($index = $parametersTableStartIndex + 2; $index -le $parametersTableEndIndex; $index++) { + $parametersList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } + + # Test + $differentiatingItems = $parameters | Where-Object { $parametersList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of template parameters missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } + + It '[] Outputs section should contain a table with these column names in order: Output Name, Type' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $readMeContent + ) + + # Get ReadMe data + $outputsSectionStartIndex = 0 + while ($readMeContent[$outputsSectionStartIndex] -notlike '*# Outputs' -and -not ($outputsSectionStartIndex -ge $readMeContent.count)) { + $outputsSectionStartIndex++ + } + + $outputsTableStartIndex = $outputsSectionStartIndex + 1 + while ($readMeContent[$outputsTableStartIndex] -notlike '*|*' -and -not ($outputsTableStartIndex -ge $readMeContent.count)) { + $outputsTableStartIndex++ + } + + $outputsTableHeader = $readMeContent[$outputsTableStartIndex].Split('|').Trim() | Where-Object { -not [String]::IsNullOrEmpty($_) } + + # Test + $expectedOutputsTableOrder = @('Output Name', 'Type') + $differentiatingItems = $expectedOutputsTableOrder | Where-Object { $outputsTableHeader -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of "Outputs" table columns missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } + + It '[] Output section should contain all outputs defined in the template file' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $templateContent, + $readMeContent + ) + + # Get ReadMe data + $outputsSectionStartIndex = 0 + while ($readMeContent[$outputsSectionStartIndex] -notlike '*# Outputs' -and -not ($outputsSectionStartIndex -ge $readMeContent.count)) { + $outputsSectionStartIndex++ + } + + $outputsTableStartIndex = $outputsSectionStartIndex + 1 + while ($readMeContent[$outputsTableStartIndex] -notlike '*|*' -and -not ($outputsTableStartIndex -ge $readMeContent.count)) { + $outputsTableStartIndex++ + } + + $outputsTableEndIndex = $outputsTableStartIndex + 2 + while ($readMeContent[$outputsTableEndIndex] -like '|*' -and -not ($outputsTableEndIndex -ge $readMeContent.count)) { + $outputsTableEndIndex++ + } + + $ReadMeoutputsList = [System.Collections.ArrayList]@() + for ($index = $outputsTableStartIndex + 2; $index -lt $outputsTableEndIndex; $index++) { + $ReadMeoutputsList += $readMeContent[$index].Split('|')[1].Replace('`', '').Trim() + } + + # Template data + $expectedOutputs = $templateContent.outputs.Keys + + # Test + $differentiatingItems = $expectedOutputs | Where-Object { $ReadMeoutputsList -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of template outputs missing in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + + $differentiatingItems = $ReadMeoutputsList | Where-Object { $expectedOutputs -notcontains $_ } + $differentiatingItems.Count | Should -Be 0 -Because ('list of excess template outputs defined in the ReadMe file [{0}] should be empty' -f ($differentiatingItems -join ',')) + } + + It '[] Template References section should contain at least one bullet point with a reference' -TestCases $readmeFolderTestCases { + param( + $moduleFolderName, + $readMeContent + ) + + $ReadmeHTML = ($readMeContent | ConvertFrom-Markdown -ErrorAction SilentlyContinue).Html + $Headings = @(@()) + foreach ($H in $ReadmeHTML) { + if ($H.Contains('') + 1 + $EndIndex = $H.LastIndexof('<') + $Headings += , (@($H.Substring($StartingIndex, $EndIndex - $StartingIndex), $ReadmeHTML.IndexOf($H))) + } + } + $HeadingIndex = $Headings | Where-Object { $_ -eq 'Template References' } + if ($HeadingIndex -eq $null) { + Write-Verbose "[Template References should contain at least one bullet point with a reference] Error At ($moduleFolderName)" -Verbose + $true | Should -Be $false + } + $StartIndex = $HeadingIndex[1] + 2 + ($ReadmeHTML[$StartIndex].Contains('
  • ')) | Should -Be $true + ($ReadmeHTML[$StartIndex].Contains('href')) | Should -Be $true + } + + } +} + +Describe 'Deployment template tests' -Tag Template { + + Context 'Deployment template tests' { + + $deploymentFolderTestCases = [System.Collections.ArrayList] @() + $deploymentFolderTestCasesException = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateContent = az bicep build --file (Join-Path $moduleFolderPath 'deploy.bicep') --stdout | ConvertFrom-Json -AsHashtable + } elseif (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateContent = Get-Content (Join-Path $moduleFolderPath 'deploy.json') -Raw | ConvertFrom-Json -AsHashtable + } else { + throw "No template file found in folder [$moduleFolderPath]" + } + + # Parameter file test cases + $parameterFileTestCases = @() + $templateFile_Parameters = $templateContent.parameters + $TemplateFile_AllParameterNames = $templateFile_Parameters.Keys | Sort-Object + $TemplateFile_RequiredParametersNames = ($templateFile_Parameters.Keys | Where-Object { -not $templateFile_Parameters[$_].ContainsKey('defaultValue') }) | Sort-Object + + if (Test-Path (Join-Path $moduleFolderPath '.parameters')) { + $ParameterFilePaths = (Get-ChildItem (Join-Path -Path $moduleFolderPath -ChildPath '.parameters' -AdditionalChildPath '*parameters.json') -Recurse -Force).FullName + foreach ($ParameterFilePath in $ParameterFilePaths) { + $parameterFile_AllParameterNames = ((Get-Content $ParameterFilePath) | ConvertFrom-Json -AsHashtable).parameters.Keys | Sort-Object + $parameterFileTestCases += @{ + parameterFile_Path = $ParameterFilePath + parameterFile_Name = Split-Path $ParameterFilePath -Leaf + parameterFile_AllParameterNames = $parameterFile_AllParameterNames + templateFile_AllParameterNames = $TemplateFile_AllParameterNames + templateFile_RequiredParametersNames = $TemplateFile_RequiredParametersNames + tokenSettings = $Settings.parameterFileTokens + } + } + } + + # Test file setup + $deploymentFolderTestCases += @{ + moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + templateContent = $templateContent + parameterFileTestCases = $parameterFileTestCases + } + } + foreach ($moduleFolderPath in $moduleFolderPathsFiltered) { + $deploymentFolderTestCasesException += @{ + moduleFolderNameException = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + templateContent = $templateContent + } + } + + It '[] the template file should not be empty' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + $templateContent | Should -Not -Be $null + } + + It '[] Template schema version should be the latest' -TestCases $deploymentFolderTestCases { + # the actual value changes depending on the scope of the template (RG, subscription, MG, tenant) !! + # https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-syntax + param( + $moduleFolderName, + $templateContent + ) + + $Schemaverion = $templateContent.'$schema' + $SchemaArray = @() + if ($Schemaverion -eq $RGdeployment) { + $SchemaOutput = $true + } elseif ($Schemaverion -eq $Subscriptiondeployment) { + $SchemaOutput = $true + } elseif ($Schemaverion -eq $MGdeployment) { + $SchemaOutput = $true + } elseif ($Schemaverion -eq $Tenantdeployment) { + $SchemaOutput = $true + } else { + $SchemaOutput = $false + } + $SchemaArray += $SchemaOutput + $SchemaArray | Should -Not -Contain $false + } + + It '[] Template schema should use HTTPS reference' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + $Schemaverion = $templateContent.'$schema' + ($Schemaverion.Substring(0, 5) -eq 'https') | Should -Be $true + } + + It '[] All apiVersion properties should be set to a static, hard-coded value' -TestCases $deploymentFolderTestCases { + #https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-best-practices + param( + $moduleFolderName, + $templateContent + ) + $ApiVersion = $templateContent.resources.apiVersion + $ApiVersionArray = @() + foreach ($API in $ApiVersion) { + if ($API.Substring(0, 2) -eq '20') { + $ApiVersionOutput = $true + } elseif ($API.substring(1, 10) -eq 'parameters') { + # An API version should not be referenced as a parameter + $ApiVersionOutput = $false + } elseif ($API.substring(1, 10) -eq 'variables') { + # An API version should not be referenced as a variable + $ApiVersionOutput = $false + } else { + $ApiVersionOutput = $false + } + $ApiVersionArray += $ApiVersionOutput + } + $ApiVersionArray | Should -Not -Contain $false + } + + It '[] the template file should contain required elements: schema, contentVersion, resources' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + $templateContent.Keys | Should -Contain '$schema' + $templateContent.Keys | Should -Contain 'contentVersion' + $templateContent.Keys | Should -Contain 'resources' + } + + It '[] If delete lock is implemented, the template should have a lock parameter with the default value of [NotSpecified]' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + if ($lock = $templateContent.parameters.lock) { + $lock.Keys | Should -Contain 'defaultValue' + $lock.defaultValue | Should -Be 'NotSpecified' + } + } + + It '[] Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + + if (-not $templateContent.parameters) { + $true | Should -Be $true + return + } + + $CamelCasingFlag = @() + $Parameter = $templateContent.parameters.Keys + foreach ($Param in $Parameter) { + if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } + + It '[] Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + + if (-not $templateContent.variables) { + $true | Should -Be $true + return + } + + $CamelCasingFlag = @() + $Variable = $templateContent.variables.Keys + + foreach ($Variab in $Variable) { + if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } + + It '[] Output names should be camel-cased (no dashes or underscores and must start with lower-case letter)' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + $CamelCasingFlag = @() + $Outputs = $templateContent.outputs.Keys + + foreach ($Output in $Outputs) { + if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { + $CamelCasingFlag += $false + } else { + $CamelCasingFlag += $true + } + } + $CamelCasingFlag | Should -Not -Contain $false + } + + It '[] CUA ID deployment should be present in the template' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + $CuaIDFlag = @() + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + if (($templateContent.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.condition -like "*[not(empty(parameters('cuaId')))]*") -or ($templateContent.resources.resources.type -ccontains 'Microsoft.Resources/deployments' -and $templateContent.resources.resources.condition -like "*[not(empty(parameters('cuaId')))]*")) { + $CuaIDFlag += $true + } else { + $CuaIDFlag += $false + } + } + $CuaIDFlag | Should -Not -Contain $false + } + + It "[] The Location should be defined as a parameter, with the default value of 'resourceGroup().Location' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + $LocationFlag = $true + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + $Locationparamoutputvalue = $templateContent.parameters.location.defaultValue + $Locationparamoutput = $templateContent.parameters.Keys + if ($Locationparamoutput -contains 'Location') { + if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { + $LocationFlag = $true + } else { + + $LocationFlag = $false + } + $LocationFlag | Should -Contain $true + } + } + } + + It "[] All resources that have a Location property should refer to the Location parameter 'parameters('Location')'" -TestCases $deploymentFolderTestCasesException { + param( + $moduleFolderNameException, + $templateContent + ) + $LocationParamFlag = @() + $Locmandoutput = $templateContent.resources + foreach ($Locmand in $Locmandoutput) { + if ($Locmand.Keys -contains 'Location' -and $Locmand.Location -eq "[parameters('Location')]") { + $LocationParamFlag += $true + } elseif ($Locmand.Keys -notcontains 'Location') { + $LocationParamFlag += $true + } elseif ($Locmand.Keys -notcontains 'resourceGroup') { + $LocationParamFlag += $true + } else { + $LocationParamFlag += $false + } + foreach ($Locm in $Locmand.resources) { + if ($Locm.Keys -contains 'Location' -and $Locm.Location -eq "[parameters('Location')]") { + $LocationParamFlag += $true + } elseif ($Locm.Keys -notcontains 'Location') { + $LocationParamFlag += $true + } else { + $LocationParamFlag += $false + } + } + } + $LocationParamFlag | Should -Not -Contain $false + } + + It '[] Standard outputs should be provided (e.g. resourceName, resourceId, resouceGroupName)' -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + + $Stdoutput = $templateContent.outputs.Keys + $i = 0 + $Schemaverion = $templateContent.'$schema' + if ((($Schemaverion.Split('/')[5]).Split('.')[0]) -eq (($RGdeployment.Split('/')[5]).Split('.')[0])) { + # Resource Group Level deployment + foreach ($Stdo in $Stdoutput) { + if ($Stdo -like '*Name*' -or $Stdo -like '*ResourceId*' -or $Stdo -like '*ResourceGroup*') { + $true | Should -Be $true + $i = $i + 1 + } + } + $i | Should -Not -BeLessThan 3 + } ElseIf ((($schemaverion.Split('/')[5]).Split('.')[0]) -eq (($Subscriptiondeployment.Split('/')[5]).Split('.')[0])) { + # Subscription Level deployment + $Stdoutput | Should -Not -BeNullOrEmpty + } + + } + + It "[] parameters' description shoud start either by 'Optional.' or 'Required.' or 'Generated.'" -TestCases $deploymentFolderTestCases { + param( + $moduleFolderName, + $templateContent + ) + + if (-not $templateContent.parameters) { + $true | Should -Be $true + return + } + + $ParamDescriptionFlag = @() + $Paramdescoutput = $templateContent.parameters.Keys + foreach ($Param in $Paramdescoutput) { + $Data = ($templateContent.parameters.$Param.metadata).description + if ($Data -like 'Optional. [a-zA-Z]*' -or $Data -like 'Required. [a-zA-Z]*' -or $Data -like 'Generated. [a-zA-Z]*') { + $true | Should -Be $true + $ParamDescriptionFlag += $true + } else { + $ParamDescriptionFlag += $false + } + } + $ParamDescriptionFlag | Should -Not -Contain $false + } + + # PARAMETER Tests + It '[] All parameters in parameters files exist in template file (deploy.json)' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $parameterFileTestCases + ) + + foreach ($parameterFileTestCase in $parameterFileTestCases) { + $parameterFile_AllParameterNames = $parameterFileTestCase.parameterFile_AllParameterNames + $templateFile_AllParameterNames = $parameterFileTestCase.templateFile_AllParameterNames + + $nonExistentParameters = $parameterFile_AllParameterNames | Where-Object { $templateFile_AllParameterNames -notcontains $_ } + $nonExistentParameters.Count | Should -Be 0 -Because ('no parameter in the parameter file should not exist in the template file. Found excess items: [{0}]' -f ($nonExistentParameters -join ', ')) + } + } + + It '[] All required parameters in template file (deploy.json) should exist in parameters files' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $parameterFileTestCases + ) + + foreach ($parameterFileTestCase in $parameterFileTestCases) { + $TemplateFile_RequiredParametersNames = $parameterFileTestCase.TemplateFile_RequiredParametersNames + $parameterFile_AllParameterNames = $parameterFileTestCase.parameterFile_AllParameterNames + + $missingParameters = $templateFile_RequiredParametersNames | Where-Object { $parameterFile_AllParameterNames -notcontains $_ } + $missingParameters.Count | Should -Be 0 -Because ('no required parameters in the template file should be missing in the parameter file. Found missing items: [{0}]' -f ($missingParameters -join ', ')) + } + } + + It '[] [Tokens] Parameter files should not contain the default Subscription ID guid' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $ParameterFileTestCases + ) + foreach ($ParameterFileTestCase in $ParameterFileTestCases) { + $ParameterFileTokenName = -join ($ParameterFileTestCase.tokenSettings.tokenPrefix, 'subscriptionId', $ParameterFileTestCase.tokenSettings.tokenSuffix) + $ParameterFileContent = Get-Content -Path $ParameterFileTestCase.parameterFile_Path + $SubscriptionIdKeyCount = ($ParameterFileContent | Select-String -Pattern '"subscriptionId"', "'subscriptionId'", '/subscriptions/' -AllMatches).Matches.Count + $SubscriptionIdValueCount = ($ParameterFileContent | Select-String -Pattern "$ParameterFileTokenName" -AllMatches).Matches.Count + $SubscriptionIdKeyCount -eq $SubscriptionIdValueCount | Should -Be $true -Because ("Parameter file should not contain the Subscription ID guid, instead should reference a token value '$ParameterFileTokenName'") + } + } + + It '[] [Tokens] Parameter files should not contain the default Tenant ID' -TestCases $deploymentFolderTestCases { + param ( + [hashtable[]] $ParameterFileTestCases + ) + foreach ($ParameterFileTestCase in $ParameterFileTestCases) { + $ParameterFileTokenName = -join ($ParameterFileTestCase.tokenSettings.tokenPrefix, 'tenantId', $ParameterFileTestCase.tokenSettings.tokenSuffix) + $ParameterFileContent = Get-Content -Path $ParameterFileTestCase.parameterFile_Path + $TenantIdKeyCount = ($ParameterFileContent | Select-String -Pattern '"tenantId"', "'tenantId'" -AllMatches).Matches.Count + $TenantIdValueCount = ($ParameterFileContent | Select-String -Pattern "$ParameterFileTokenName" -AllMatches).Matches.Count + $TenantIdKeyCount -eq $TenantIdValueCount | Should -Be $true -Because ("Parameter file should not contain the Tenant ID guid, instead should reference a token value '$ParameterFileTokenName'") + } + } + } +} + +Describe "API version tests [All apiVersions in the template should be 'recent']" -Tag ApiCheck { + + $testCases = @() + $ApiVersions = Get-AzResourceProvider -ListAvailable + foreach ($moduleFolderPath in $moduleFolderPathsFiltered) { + + $moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/arm/')[1] + + if (Test-Path (Join-Path $moduleFolderPath 'deploy.bicep')) { + $templateContent = az bicep build --file (Join-Path $moduleFolderPath 'deploy.bicep') --stdout | ConvertFrom-Json -AsHashtable + } elseif (Test-Path (Join-Path $moduleFolderPath 'deploy.json')) { + $templateContent = Get-Content (Join-Path $moduleFolderPath 'deploy.json') -Raw | ConvertFrom-Json -AsHashtable + } else { + throw "No template file found in folder [$moduleFolderPath]" + } + + $nestedResources = Get-NestedResourceList -TemplateContent $templateContent | Where-Object { + $_.type -notin @('Microsoft.Resources/deployments') -and $_ + } | Select-Object 'Type', 'ApiVersion' -Unique | Sort-Object Type + + foreach ($resource in $nestedResources) { + + switch ($resource.type) { + { $PSItem -like '*diagnosticsettings*' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'diagnosticsettings' + ProviderNamespace = 'Microsoft.insights' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + } + break + } + { $PSItem -like '*locks' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'locks' + ProviderNamespace = 'Microsoft.Authorization' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + } + break + } + { $PSItem -like '*roleAssignments' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'roleassignments' + ProviderNamespace = 'Microsoft.Authorization' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + } + break + } + { $PSItem -like '*privateEndpoints' } { + $testCases += @{ + moduleName = $moduleFolderName + resourceType = 'privateEndpoints' + ProviderNamespace = 'Microsoft.Network' + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + } + break + } + Default { + $ProviderNamespace, $rest = $resource.Type.Split('/') + $testCases += @{ + moduleName = $moduleFolderName + resourceType = $rest -join '/' + ProviderNamespace = $ProviderNamespace + TargetApi = $resource.ApiVersion + AvailableApiVersions = $ApiVersions + } + break + } + } + } + } + + It 'In [] used resource type [] should use on of the recent API version(s). Currently using []' -TestCases $TestCases { + param( + $moduleName, + $resourceType, + $TargetApi, + $ProviderNamespace, + $AvailableApiVersions + ) + + $namespaceResourceTypes = ($AvailableApiVersions | Where-Object { $_.ProviderNamespace -eq $ProviderNamespace }).ResourceTypes + $resourceTypeApiVersions = ($namespaceResourceTypes | Where-Object { $_.ResourceTypeName -eq $resourceType }).ApiVersions + + if (-not $resourceTypeApiVersions) { + Write-Warning ('[API Test] We are currently unable to determine the available API versions for resource type [{0}/{1}]' -f $ProviderNamespace, $resourceType) + continue + } + + # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview + $approvedApiVersions = @() + $approvedApiVersions += $resourceTypeApiVersions | Select-Object -First 5 + $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -First 3 + ($approvedApiVersions | Select-Object -Unique) | Should -Contain $TargetApi + } +} diff --git a/carml/1.0.0/shared/helper.psm1 b/carml/1.0.0/shared/helper.psm1 new file mode 100644 index 000000000..d793e9afa --- /dev/null +++ b/carml/1.0.0/shared/helper.psm1 @@ -0,0 +1,39 @@ +<# +.SYNOPSIS +Get a list of all resources (provider + service) in the given template content + +.DESCRIPTION +Get a list of all resources (provider + service) in the given template content. Crawls through any children & nested deployment templates. + +.PARAMETER TemplateFileContent +Mandatory. The template file content object to crawl data from + +.EXAMPLE +Get-NestedResourceList -TemplateFileContent @{ resource = @{}; ... } + +Returns a list of all resources in the given template object +#> +function Get-NestedResourceList { + + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [hashtable] $TemplateContent + ) + + $res = @() + $currLevelResources = @() + if ($TemplateContent.resources) { + $currLevelResources += $TemplateContent.resources + } + foreach ($resource in $currLevelResources) { + $res += $resource + + if ($resource.type -eq 'Microsoft.Resources/deployments') { + $res += Get-NestedResourceList -TemplateContent $resource.properties.template + } else { + $res += Get-NestedResourceList -TemplateContent $resource + } + } + return $res +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..7271e1d83 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json new file mode 100644 index 000000000..f140b8c7e --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..de4e5052a --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json new file mode 100644 index 000000000..e28b39cfd --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..ebadf2e43 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/sub.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": { + "name": { + "value": "<>-min-sub-polAss" + }, + "policyDefinitionID": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json new file mode 100644 index 000000000..cc671f092 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/.parameters/sub.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": "<>-sub-polAss" + }, + "displayName": { + "value": "[Display Name] Policy Assignment at the subscription scope" + }, + "description": { + "value": "[Description] Policy Assignment at the subscription 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" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyAssignments/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyAssignments/deploy.bicep new file mode 100644 index 000000000..8a4f9a503 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/deploy.bicep @@ -0,0 +1,140 @@ +targetScope = 'managementGroup' + +@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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment') +param subscriptionId string = '' + +@sys.description('Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment') +param resourceGroupName string = '' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policyAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + managementGroupId: managementGroupId + location: location + } +} + +module policyAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + subscriptionId: subscriptionId + location: location + } +} + +module policyAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + subscriptionId: subscriptionId + location: location + } +} + +@sys.description('Policy Assignment 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(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(subscriptionId) && empty(resourceGroupName) ? policyAssignment_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_sub.outputs.resourceId : policyAssignment_rg.outputs.resourceId) diff --git a/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep new file mode 100644 index 000000000..9f6d4b94b --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep @@ -0,0 +1,108 @@ +targetScope = 'managementGroup' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +var nonComplianceMessage_var = { + message: !empty(nonComplianceMessage) ? nonComplianceMessage : null +} + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(managementGroupId, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@sys.description('Policy Assignment resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyAssignments', policyAssignment.name) diff --git a/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/readme.md new file mode 100644 index 000000000..842e05c93 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/readme.md @@ -0,0 +1,55 @@ +# Policy Assignment on Management Group level `[Microsoft.Authorization/policyAssignments/managementGroup]` + +With this module you can perform policy assignments on a management group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Location for all resources. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | + + +## 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/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/version.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/readme.md b/carml/1.0.1/Microsoft.Authorization/policyAssignments/readme.md new file mode 100644 index 000000000..194aebc90 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/readme.md @@ -0,0 +1,116 @@ +# Policy Assignments `[Microsoft.Authorization/policyAssignments]` + +With this module you can perform policy assignments across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope, 64 characters for subscription and resource group scopes. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Location for all resources. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | +| `resourceGroupName` | string | `''` | | The Target Scope for the Policy. The name of the resource group for the policy assignment | +| `subscriptionId` | string | `''` | | The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `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/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep new file mode 100644 index 000000000..6eaf1e635 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep @@ -0,0 +1,113 @@ +targetScope = 'resourceGroup' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +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. 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. If not provided, will use the current scope for deployment.') +param resourceGroupName string = resourceGroup().name + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(subscriptionId, resourceGroupName, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@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/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md new file mode 100644 index 000000000..14c90f1d2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md @@ -0,0 +1,57 @@ +# Policy Assignment on Resource Group level `[Microsoft.Authorization/policyAssignments/resourceGroup]` + +With this module you can perform policy assignments on a resource group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 64 characters for resource group scope. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `metadata` | object | `{object}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | 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. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/version.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep new file mode 100644 index 000000000..93824ae2b --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep @@ -0,0 +1,108 @@ +targetScope = 'subscription' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +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. If not provided, will use the current scope for deployment.') +param subscriptionId string = subscription().subscriptionId + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(subscriptionId, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@sys.description('Policy Assignment resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyAssignments', policyAssignment.name) diff --git a/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/readme.md b/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/readme.md new file mode 100644 index 000000000..24bde8974 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/readme.md @@ -0,0 +1,55 @@ +# Policy Assignment on Subscription level `[Microsoft.Authorization/policyAssignments/subscription]` + +With this module you can perform policy assignments on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 64 characters for subscription scope. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Location for all resources. | +| `metadata` | object | `{object}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/version.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyAssignments/version.json b/carml/1.0.1/Microsoft.Authorization/policyAssignments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyAssignments/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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..431a0f6f5 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..7196de615 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..f2cd03cfb --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-sub-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" + } + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..e44512751 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/.parameters/sub.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": "<>-sub-policyDef" + }, + "displayName": { + "value": "[DisplayName] This policy definition is deployed at subscription scope" + }, + "description": { + "value": "[Description] This policy definition is deployed at subscription 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" + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyDefinitions/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/deploy.bicep new file mode 100644 index 000000000..864abef50 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/deploy.bicep @@ -0,0 +1,97 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +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). 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 = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policyDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + managementGroupId: managementGroupId + mode: mode + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyRule: policyRule + location: location + } +} + +module policyDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + subscriptionId: subscriptionId + mode: mode + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyRule: policyRule + location: location + } +} + +@sys.description('Policy Definition Name') +output name string = empty(subscriptionId) ? policyDefinition_mg.outputs.name : policyDefinition_sub.outputs.name + +@sys.description('Policy Definition resource ID') +output resourceId string = empty(subscriptionId) ? policyDefinition_mg.outputs.resourceId : policyDefinition_sub.outputs.resourceId + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = empty(subscriptionId) ? policyDefinition_mg.outputs.roleDefinitionIds : policyDefinition_sub.outputs.roleDefinitionIds diff --git a/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..c577623b5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +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. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + mode: mode + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = policyDefinition.name + +@sys.description('Policy Definition resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyDefinitions', policyDefinition.name) + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = (contains(policyDefinition.properties.policyRule.then, 'details') ? ((contains(policyDefinition.properties.policyRule.then.details, 'roleDefinitionIds') ? policyDefinition.properties.policyRule.then.details.roleDefinitionIds : [])) : []) diff --git a/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..97c0d07e7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md @@ -0,0 +1,49 @@ +# Policy Definitions on Management Group level `[Microsoft.Authorization/policyDefinitions/managementGroup]` + +With this module you can create policy definitions on a management group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy definition. Maximum length is 64 characters. | +| `policyRule` | object | The Policy Rule details for the Policy Definition | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The policy definition description. | +| `displayName` | string | `''` | | The display name of the policy definition. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | The group ID of the Management Group. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | 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]` | The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `parameters` | object | `{object}` | | The policy definition parameters that can be used in policy definition references. | + + +## 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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/version.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/readme.md b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/readme.md new file mode 100644 index 000000000..8c39b11cc --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/readme.md @@ -0,0 +1,94 @@ +# Policy Definitions `[Microsoft.Authorization/policyDefinitions]` + +With this module you can create policy definitions across the management group or subscription scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy definition. Maximum length is 64 characters for management group scope and subscription scope. | +| `policyRule` | object | The Policy Rule details for the Policy Definition | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The policy definition description. | +| `displayName` | string | `''` | | The display name of the policy definition. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | 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]` | The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `parameters` | object | `{object}` | | The policy definition parameters that can be used in policy definition references. | +| `subscriptionId` | string | `''` | | The subscription ID of the subscription (Scope). Cannot be used with managementGroupId | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +## 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 | +| :-- | :-- | :-- | +| `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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..46b723022 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'subscription' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Required. The Policy Rule details for the Policy Definition') +param policyRule object + +@sys.description('Optional. The subscription ID of the subscription') +param subscriptionId string = subscription().subscriptionId + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + mode: mode + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = policyDefinition.name + +@sys.description('Policy Definition resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyDefinitions', policyDefinition.name) + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = (contains(policyDefinition.properties.policyRule.then, 'details') ? ((contains(policyDefinition.properties.policyRule.then.details, 'roleDefinitionIds') ? policyDefinition.properties.policyRule.then.details.roleDefinitionIds : [])) : []) diff --git a/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/readme.md b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/readme.md new file mode 100644 index 000000000..3c527a4a1 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/readme.md @@ -0,0 +1,49 @@ +# Policy Definitions on Subscription level `[Microsoft.Authorization/policyDefinitions/subscription]` + +With this module you can create policy definitions on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy definition. Maximum length is 64 characters. | +| `policyRule` | object | The Policy Rule details for the Policy Definition | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The policy definition description. | +| `displayName` | string | `''` | | The display name of the policy definition. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `metadata` | object | `{object}` | | 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]` | The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `parameters` | object | `{object}` | | The policy definition parameters that can be used in policy definition references. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/version.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyDefinitions/version.json b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyDefinitions/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..f5816fcd6 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json new file mode 100644 index 000000000..2c76ecb64 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..2573b17fe --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json new file mode 100644 index 000000000..68fda77de --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..920e7d2ad --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/sub.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": { + "name": { + "value": "<>-min-sub-polexem" + }, + "policyAssignmentId": { + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json new file mode 100644 index 000000000..02b3e9037 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/.parameters/sub.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": "<>-sub-polexem" + }, + "displayName": { + "value": "[Display Name] policy exempt (subscription 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": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policyExemptions/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyExemptions/deploy.bicep new file mode 100644 index 000000000..49bd4a79d --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/deploy.bicep @@ -0,0 +1,119 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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 = '' + +@sys.description('Optional. The name of the resource group to be exempted from the policy assignment. Must also use the subscription ID parameter.') +param resourceGroupName string = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policyExemption_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + managementGroupId: managementGroupId + location: location + } +} + +module policyExemption_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + subscriptionId: subscriptionId + location: location + } +} + +module policyExemption_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + } +} + +@sys.description('Policy Exemption 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(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(subscriptionId) && empty(resourceGroupName) ? policyExemption_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_sub.outputs.scope : policyExemption_rg.outputs.scope) diff --git a/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep new file mode 100644 index 000000000..2e79abcdd --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'managementGroup' + +@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 assignment. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@sys.description('Policy Exemption Scope') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) diff --git a/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/readme.md new file mode 100644 index 000000000..cdab3c4be --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/readme.md @@ -0,0 +1,50 @@ +# Policy Exemptions on Management Group level `[Microsoft.Authorization/policyExemptions/managementGroup]` + +With this module you can create policy exemptions on a management group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for management group scope. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | 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/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/version.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/readme.md b/carml/1.0.1/Microsoft.Authorization/policyExemptions/readme.md new file mode 100644 index 000000000..db8f04514 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/readme.md @@ -0,0 +1,116 @@ +# Policy Exemptions `[Microsoft.Authorization/policyExemptions]` + +With this module you can create policy exemptions across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for management group, subscription and resource group scopes. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy exemption. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `resourceGroupName` | string | `''` | | The name of the resource group to be exempted from the policy assignment. Must also use the subscription ID parameter. | +| `subscriptionId` | string | `''` | | The subscription ID of the subscription to be exempted from the policy assignment. Cannot use with management group ID parameter. | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | Policy Exemption Name | +| `resourceId` | string | Policy Exemption resource ID | +| `scope` | string | Policy Exemption Scope | + +## Considerations + +- Policy Exemptions have a dependency on Policy Assignments being applied before creating an exemption. You can use the Policy Assignment [Module](../policyAssignments/deploy.bicep) to deploy a Policy Assignment and then create the exemption for it on the required scope. + +## Template references + +- [Policyexemptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-07-01-preview/policyExemptions) diff --git a/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep new file mode 100644 index 000000000..8551f2bb9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep @@ -0,0 +1,77 @@ +targetScope = 'resourceGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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. If not provided, will use the current scope for deployment.') +param resourceGroupName string = resourceGroup().name + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = az.resourceId(subscriptionId, resourceGroupName, 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@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/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md new file mode 100644 index 000000000..cb8847d10 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md @@ -0,0 +1,51 @@ +# Policy Exemptions on Resource Group level `[Microsoft.Authorization/policyExemptions/resourceGroup]` + +With this module you can create policy exemptions on a resource group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for resource group scope. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy exemption. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | 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]` | | 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/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/version.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep new file mode 100644 index 000000000..0106c0b91 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'subscription' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. If not provided, will use the current scope for deployment.') +param subscriptionId string = subscription().subscriptionId + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@sys.description('Policy Exemption Scope') +output scope string = subscription().id diff --git a/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/readme.md b/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/readme.md new file mode 100644 index 000000000..e64dcf176 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/readme.md @@ -0,0 +1,50 @@ +# Policy Exemptions on Subscription level `[Microsoft.Authorization/policyExemptions/subscription]` + +With this module you can create policy exemptions on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for subscription scope. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy exemption. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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]` | | Location deployment metadata. | +| `metadata` | object | `{object}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/version.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policyExemptions/version.json b/carml/1.0.1/Microsoft.Authorization/policyExemptions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policyExemptions/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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..92f9d4ac2 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..029e2d47c --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..f6a7e68f6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-sub-min-policySet" + }, + "policyDefinitions": { + "value": [ + { + "parameters": { + "listOfAllowedLocations": { + "value": [ + "australiaeast" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c" + } + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..16a92428b --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/.parameters/sub.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": "<>-sub-policySet" + }, + "displayName": { + "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": [ + { + "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" + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/deploy.bicep new file mode 100644 index 000000000..0b2312bc6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/deploy.bicep @@ -0,0 +1,87 @@ +targetScope = 'managementGroup' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@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). 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 = '' + +@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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policySetDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + managementGroupId: managementGroupId + location: location + } +} + +module policySetDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + subscriptionId: subscriptionId + location: location + } +} + +@sys.description('Policy Set Definition 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(subscriptionId) ? policySetDefinition_mg.outputs.resourceId : policySetDefinition_sub.outputs.resourceId diff --git a/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..3e6ab1886 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,65 @@ +targetScope = 'managementGroup' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description name of the Set Definition (Initiative)') +param description 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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policySetDefinition 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + } +} + +@sys.description('Policy Set Definition Name') +output name string = policySetDefinition.name + +@sys.description('Policy Set Definition resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policySetDefinitions', policySetDefinition.name) diff --git a/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..44cca5380 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md @@ -0,0 +1,48 @@ +# 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. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope. | +| `policyDefinitions` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description name of the Set Definition (Initiative) | +| `displayName` | string | `''` | The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | The group ID of the Management Group. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `parameters` | object | `{object}` | The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | + + +## 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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/readme.md b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/readme.md new file mode 100644 index 000000000..313094f8f --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/readme.md @@ -0,0 +1,98 @@ +# Policy Set Definitions `[Microsoft.Authorization/policySetDefinitions]` + +With this module you can create policy set definitions across the management group or subscription scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope and 64 characters for subscription scope. | +| `policyDefinitions` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description name of the Set Definition (Initiative) | +| `displayName` | string | `''` | The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `parameters` | object | `{object}` | The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | +| `subscriptionId` | string | `''` | The subscription ID of the subscription (Scope). Cannot be used with managementGroupId | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +## 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 | +| :-- | :-- | :-- | +| `name` | string | Policy Set Definition Name | +| `resourceId` | string | Policy Set Definition resource ID | + +## Considerations + +- Policy Set Definitions (Initiatives) have a dependency on Policy Assignments being applied before creating an initiative. You can use the Policy Assignment [Module](../policyDefinitions/deploy.bicep) to deploy a Policy Definition and then create an initiative for it on the required scope. + +## Template references + +- [Policysetdefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policySetDefinitions) diff --git a/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..cf269aa4b --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep @@ -0,0 +1,65 @@ +targetScope = 'subscription' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description name of the Set Definition (Initiative)') +param description string = '' + +@sys.description('Optional. The subscription ID of the subscription') +param subscriptionId string = subscription().subscriptionId + +@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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policySetDefinition 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + } +} + +@sys.description('Policy Set Definition Name') +output name string = policySetDefinition.name + +@sys.description('Policy Set Definition resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policySetDefinitions', policySetDefinition.name) diff --git a/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/readme.md b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/readme.md new file mode 100644 index 000000000..3c4bf8fe0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/readme.md @@ -0,0 +1,48 @@ +# Policy Set Definitions on Subscription level `[Microsoft.Authorization/policySetDefinitions/subscription]` + +With this module you can create policy set definitions on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy Set Definition (Initiative). Maximum length is 64 characters for subscription scope. | +| `policyDefinitions` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description name of the Set Definition (Initiative) | +| `displayName` | string | `''` | The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `metadata` | object | `{object}` | The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `parameters` | object | `{object}` | The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | +| `subscriptionId` | string | `[subscription().subscriptionId]` | 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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/version.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/version.json b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/policySetDefinitions/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..02a409875 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json new file mode 100644 index 000000000..e6362b62a --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..6011dc7e9 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json new file mode 100644 index 000000000..faf9fc3d9 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..2a90f97fb --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/sub.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": { + "roleDefinitionIdOrName": { + "value": "Storage Queue Data Reader" + }, + "principalId": { + "value": "<>" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json new file mode 100644 index 000000000..346ba64c0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/.parameters/sub.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 (subscription scope)" + }, + "principalId": { + "value": "<>" + }, + "principalType": { + "value": "ServicePrincipal" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/roleAssignments/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleAssignments/deploy.bicep new file mode 100644 index 000000000..2303db55c --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/deploy.bicep @@ -0,0 +1,118 @@ +targetScope = 'managementGroup' + +@sys.description('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\'') +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 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 not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. Location deployment metadata.') +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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module roleAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-MG-Module' + scope: managementGroup(managementGroupId) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + managementGroupId: managementGroupId + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + location: location + } +} + +module roleAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-Sub-Module' + scope: subscription(subscriptionId) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + subscriptionId: subscriptionId + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + location: location + } +} + +module roleAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + } +} + +@sys.description('The GUID of the Role Assignment') +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(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(subscriptionId) && empty(resourceGroupName) ? roleAssignment_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_sub.outputs.scope : roleAssignment_rg.outputs.scope) diff --git a/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep new file mode 100644 index 000000000..1226036c2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep @@ -0,0 +1,363 @@ +targetScope = 'managementGroup' + +@sys.description('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\'') +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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(managementGroupId, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) + +@sys.description('The scope this Role Assignment applies to') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/roleAssignments', roleAssignment.name) diff --git a/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/readme.md new file mode 100644 index 000000000..649f825bc --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/readme.md @@ -0,0 +1,49 @@ +# Role Assignment on Management Group level `[Microsoft.Authorization/roleAssignments/managementGroup]` + +With this module you can perform role assignments on a management group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | + + +## 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/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/version.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/readme.md b/carml/1.0.1/Microsoft.Authorization/roleAssignments/readme.md new file mode 100644 index 000000000..f5b19e511 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/readme.md @@ -0,0 +1,115 @@ +# Role Assignments `[Microsoft.Authorization/roleAssignments]` + +This module deploys Role Assignments across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | +| `resourceGroupName` | string | `''` | | 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. | +| `subscriptionId` | string | `''` | | 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. | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Assignment | +| `resourceId` | string | The resource ID of the Role Assignment | +| `scope` | string | The scope this Role Assignment applies to | + +## Considerations + +This module can be deployed at the management group, subscription or resource group level + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep new file mode 100644 index 000000000..7e2144146 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep @@ -0,0 +1,365 @@ +targetScope = 'resourceGroup' + +@sys.description('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\'') +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 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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(subscriptionId, resourceGroupName, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +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/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md new file mode 100644 index 000000000..2aa023c01 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md @@ -0,0 +1,50 @@ +# Role Assignment on Resource Group level `[Microsoft.Authorization/roleAssignments/resourceGroup]` + +With this module you can perform role assignments on a resource group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/version.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep new file mode 100644 index 000000000..d6569d6fa --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep @@ -0,0 +1,363 @@ +targetScope = 'subscription' + +@sys.description('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\'') +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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(subscriptionId, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +output scope string = subscription().id + +@sys.description('The scope this Role Assignment applies to') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/roleAssignments', roleAssignment.name) diff --git a/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/readme.md b/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/readme.md new file mode 100644 index 000000000..a9f6fa476 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/readme.md @@ -0,0 +1,49 @@ +# Role Assignment on Subscription level `[Microsoft.Authorization/roleAssignments/subscription]` + +With this module you can perform role assignments on a subscription level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/version.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleAssignments/version.json b/carml/1.0.1/Microsoft.Authorization/roleAssignments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleAssignments/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..c4a88ba9e --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..d49ce1cae --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..cf6825cc0 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json new file mode 100644 index 000000000..c27ff2f86 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..87bbbc20b --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/sub.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": { + "roleName": { + "value": "<>-az-testRole-sub-min" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..62e03ca98 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/.parameters/sub.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-sub" + }, + "description": { + "value": "Test Custom Role Definition Standard (subscription 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/<>" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.0.1/Microsoft.Authorization/roleDefinitions/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/deploy.bicep new file mode 100644 index 000000000..8a3cb22cb --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/deploy.bicep @@ -0,0 +1,105 @@ +targetScope = 'managementGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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 = '' + +@sys.description('Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to.') +param resourceGroupName string = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Role definition assignable scopes. If not provided, will use the current scope provided.') +param assignableScopes array = [] + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module roleDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + managementGroupId: managementGroupId + location: location + } +} + +module roleDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + dataActions: !empty(dataActions) ? dataActions : [] + notDataActions: !empty(notDataActions) ? notDataActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + subscriptionId: subscriptionId + location: location + } +} + +module roleDefinition_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + dataActions: !empty(dataActions) ? dataActions : [] + notDataActions: !empty(notDataActions) ? notDataActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + } +} + +@sys.description('The GUID of the Role Definition') +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(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(subscriptionId) && empty(resourceGroupName) ? roleDefinition_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_sub.outputs.scope : roleDefinition_rg.outputs.scope) diff --git a/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..1b1bafe1e --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,63 @@ +targetScope = 'managementGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@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 = [] + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, managementGroupId) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + } + ] + assignableScopes: assignableScopes == [] ? array(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId)) : assignableScopes + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) + +@sys.description('The resource ID of the Role Definition') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/roleDefinitions', roleDefinition.name) diff --git a/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..0969defa3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md @@ -0,0 +1,47 @@ +# Role Definitions on Management Group level `[Microsoft.Authorization/roleDefinitions/managementGroup]` + +With this module you can create role definitions on a management group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | 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 | `[]` | List of denied actions. | + + +## 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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/version.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/readme.md b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/readme.md new file mode 100644 index 000000000..818735d01 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/readme.md @@ -0,0 +1,119 @@ +# Role Definitions `[Microsoft.Authorization/roleDefinitions]` + +This module deploys custom RBAC Role Definitions across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | 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 | `[]` | List of denied actions. | +| `notDataActions` | array | `[]` | List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `resourceGroupName` | string | `''` | The name of the Resource Group where the Role Definition and Target Scope will be applied to. | +| `subscriptionId` | string | `''` | The subscription ID where the Role Definition and Target Scope will be applied to. Use for both Subscription level and Resource Group Level. | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Definition | +| `resourceId` | string | The resource ID of the Role Definition | +| `roleDefinitionScope` | string | The scope this Role Definition applies to | + +## Considerations + +This module can be deployed both at subscription or resource group level: + +- To deploy the module at resource group level, provide a valid name of an existing Resource Group in the `resourceGroupName` parameter and an existing subscription ID in the `subscriptionId` parameter. +- To deploy the module at the subscription level, provide an existing subscription ID in the `subscriptionId` parameter. +- To deploy the module at the management group level, provide an existing management group ID in the `managementGroupId` parameter. + +## Template references + +- [Roledefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2018-01-01-preview/roleDefinitions) diff --git a/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep new file mode 100644 index 000000000..9ba0c6ec4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep @@ -0,0 +1,73 @@ +targetScope = 'resourceGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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. 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. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, subscriptionId, resourceGroupName) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + dataActions: dataActions + notDataActions: notDataActions + } + ] + assignableScopes: assignableScopes == [] ? array(resourceGroup().id) : assignableScopes + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md new file mode 100644 index 000000000..d9c3b75bf --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md @@ -0,0 +1,50 @@ +# Role Definitions on Resource Group level `[Microsoft.Authorization/roleDefinitions/resourceGroup]` + +With this module you can create role definitions on a resource group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `notActions` | array | `[]` | List of denied actions. | +| `notDataActions` | array | `[]` | List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `resourceGroupName` | string | `[resourceGroup().name]` | 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. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | 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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..bb0746034 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep @@ -0,0 +1,71 @@ +targetScope = 'subscription' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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.') +param assignableScopes array = [] + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, subscriptionId) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + dataActions: dataActions + notDataActions: notDataActions + } + ] + assignableScopes: !empty(assignableScopes) ? assignableScopes : array(subscription().id) + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +output scope string = subscription().id + +@sys.description('The resource ID of the Role Definition') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/roleDefinitions', roleDefinition.name) diff --git a/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/readme.md b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/readme.md new file mode 100644 index 000000000..694f9f6d5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/readme.md @@ -0,0 +1,49 @@ +# Role Definitions on Subscription level `[Microsoft.Authorization/roleDefinitions/subscription]` + +With this module you can create role definitions on a subscription level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `notActions` | array | `[]` | List of denied actions. | +| `notDataActions` | array | `[]` | List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `subscriptionId` | string | `[subscription().subscriptionId]` | 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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/version.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/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/carml/1.0.1/Microsoft.Authorization/roleDefinitions/version.json b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Authorization/roleDefinitions/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/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_linkedService.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_linkedService.bicep new file mode 100644 index 000000000..a5db7f142 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_linkedService.bicep @@ -0,0 +1,37 @@ +@description('Required. Name of the link') +param name string + +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access.') +param resourceId string = '' + +@description('Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access. ') +param writeAccessResourceId string = '' + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource linkedService 'Microsoft.OperationalInsights/workspaces/linkedServices@2020-03-01-preview' = { + name: name + parent: logAnalyticsWorkspace + tags: tags + properties: { + resourceId: !empty(resourceId) ? resourceId : null + writeAccessResourceId: !empty(writeAccessResourceId) ? writeAccessResourceId : null + } +} + +@description('The name of the deployed linked service') +output name string = linkedService.name + +@description('The resource ID of the deployed linked service') +output resourceId string = linkedService.id + +@description('The resource group where the linked service is deployed') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..26e201e43 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..679f31345 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') + 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') + 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(automationAccount.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: automationAccount +}] diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_solution.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_solution.bicep new file mode 100644 index 000000000..b6cbf586e --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.bicep/nested_solution.bicep @@ -0,0 +1,43 @@ +@description('Required. Name of the solution') +param name string + +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The product of the deployed solution. For gallery solution, it is OMSGallery.') +param product string = 'OMSGallery' + +@description('Optional. The publisher name of the deployed solution. For gallery solution, it is Microsoft.') +param publisher string = 'Microsoft' + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { + name: logAnalyticsWorkspaceName +} + +var solutionName = '${name}(${logAnalyticsWorkspace.name})' + +resource solution 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { + name: solutionName + location: location + properties: { + workspaceResourceId: logAnalyticsWorkspace.id + } + plan: { + name: solutionName + promotionCode: '' + product: '${product}/${name}' + publisher: publisher + } +} + +@description('The name of the deployed solution') +output name string = solution.name + +@description('The resource ID of the deployed solution') +output resourceId string = solution.id + +@description('The resource group where the solution is deployed') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/encr.parameters.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/encr.parameters.json new file mode 100644 index 000000000..c396172aa --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/encr.parameters.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-wd-aut-encr-001" + }, + "encryptionKeySource" : { + "value" : "Microsoft.Keyvault" + }, + "encryptionUserAssignedIdentity": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001" // this identity needs to be one of the identities defined in userAssignedIdentities section + }, + "keyName" : { + "value" : "keyEncryptionKey" + }, + "keyvaultUri" : { + "value" : "https://adp-carml-az-kv-nopr-002.vault.azure.net/" + }, + "keyVersion" : { + "value" : "9917c14be51d4d93b37218de7d326f60" + }, + + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..36d11228d --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-wd-aut-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/parameters.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/parameters.json new file mode 100644 index 000000000..8aa13a2ed --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/.parameters/parameters.json @@ -0,0 +1,192 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-wd-aut-x-001" + }, + "schedules": { + "value": [ + { + "name": "TestSchedule", + "startTime": "", + "expiryTime": "9999-12-31T23:59:00+00:00", + "interval": 15, + "frequency": "Minute", + "timeZone": "Europe/Berlin", + "advancedSchedule": {} + } + ] + }, + "modules": { + "value": [ + { + "name": "PSWindowsUpdate", + "version": "latest", + "uri": "https://www.powershellgallery.com/api/v2/package" + } + ] + }, + "runbooks": { + "value": [ + { + "name": "TestRunbook", + "runbookType": "PowerShell", + "description": "Test runbook", + "uri": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1", + "version": "1.0.0.0" + } + ] + }, + "jobSchedules": { + "value": [ + { + "scheduleName": "TestSchedule", + "runbookName": "TestRunbook" + } + ] + }, + "variables": { + "value": [ + { + "name": "TestString", + "value": "\"TestString\"", + "description": "TestStringDescription" + }, + { + "name": "TestInteger", + "value": "500", + "description": "TestIntegerDescription" + }, + { + "name": "TestBoolean", + "value": "false", + "description": "TestBooleanDescription" + }, + { + "name": "TestDateTime", + "value": "\"\\/Date(1637934042656)\\/\"", + "description": "TestDateTimeDescription", + "isEncrypted": false + }, + { + "name": "TestEncryptedVariable", + "value": "\"TestEncryptedValue\"", + "description": "TestEncryptedDescription" + } + ] + }, + "linkedWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-aut-001" + }, + "gallerySolutions": { + "value": [ + "Updates" + ] + }, + "softwareUpdateConfigurations": { + "value": [ + { + "name": "Windows_ZeroDay", + "frequency": "Month", + "operatingSystem": "Windows", + "rebootSetting": "IfRequired", + "scopeByTags": { + "Update": [ + "Automatic-Wave1" + ] + }, + "maintenanceWindow": "PT4H", + "updateClassifications": [ + "Critical", + "Security", + "UpdateRollup", + "FeaturePack", + "ServicePack", + "Definition", + "Tools", + "Updates" + ], + "includeUpdates": [ + "654321" + ], + "excludeUpdates": [ + "123456" + ], + "interval": 1, + "monthlyOccurrences": [ + { + "occurrence": 3, + "day": "Friday" + } + ], + "startTime": "22:00" + }, + { + "name": "Linux_ZeroDay", + "frequency": "OneTime", + "operatingSystem": "Linux", + "rebootSetting": "IfRequired", + "maintenanceWindow": "PT4H", + "updateClassifications": [ + "Critical", + "Security", + "Other" + ], + "includeUpdates": [ + "kernel" + ], + "excludeUpdates": [ + "icacls" + ], + "startTime": "22:00" + } + ] + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "Webhook" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "DSCAndHybridWorker" + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/deploy.bicep new file mode 100644 index 000000000..40d20e55f --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/deploy.bicep @@ -0,0 +1,378 @@ +@description('Required. Name of the Automation Account.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. SKU name of the account.') +@allowed([ + 'Free' + 'Basic' +]) +param skuName string = 'Basic' + +@description('Optional. User identity used for CMK. If you set encryptionKeySource as Microsoft.Keyvault encryptionUserAssignedIdentity is required.') +param encryptionUserAssignedIdentity string = '' + +@description('Optional. Encryption Key Source. For security reasons it is recommended to use Microsoft.Keyvault if custom keys are available.') +@allowed([ + 'Microsoft.Automation' + 'Microsoft.Keyvault' +]) +param encryptionKeySource string = 'Microsoft.Automation' + +@description('Optional. The name of key used to encrypt data. This parameter is needed only if you enable Microsoft.Keyvault as encryptionKeySource.') +param keyName string = '' + +@description('Optional. The URI of the key vault key used to encrypt data. This parameter is needed only if you enable Microsoft.Keyvault as encryptionKeySource.') +param keyvaultUri string = '' + +@description('Optional. The key version of the key used to encrypt data. This parameter is needed only if you enable Microsoft.Keyvault as encryptionKeySource.') +param keyVersion string = '' + +@description('Optional. List of modules to be created in the automation account.') +param modules array = [] + +@description('Optional. List of runbooks to be created in the automation account.') +param runbooks array = [] + +@description('Optional. List of schedules to be created in the automation account.') +param schedules array = [] + +@description('Optional. List of jobSchedules to be created in the automation account.') +param jobSchedules array = [] + +@description('Optional. List of variables to be created in the automation account.') +param variables array = [] + +@description('Optional. ID of the log analytics workspace to be linked to the deployed automation account.') +param linkedWorkspaceId string = '' + +@description('Optional. List of gallerySolutions to be created in the linked log analytics workspace') +param gallerySolutions array = [] + +@description('Optional. List of softwareUpdateConfigurations to be created in the automation account') +param softwareUpdateConfigurations array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@minValue(0) +@maxValue(365) +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the Automation Account resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'JobLogs' + 'JobStreams' + 'DscNodeStatus' +]) +param diagnosticLogCategoriesToEnable array = [ + 'JobLogs' + 'JobStreams' + 'DscNodeStatus' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' = { + name: name + location: location + tags: tags + identity: identity + properties: { + sku: { + name: skuName + } + encryption: { + identity: encryptionKeySource == 'Microsoft.Keyvault' ? { + userAssignedIdentity: any(encryptionUserAssignedIdentity) + } : null + keySource: encryptionKeySource + keyVaultProperties: encryptionKeySource == 'Microsoft.Keyvault' ? { + keyName: keyName + keyvaultUri: keyvaultUri + keyVersion: keyVersion + } : null + } + } +} + +module automationAccount_modules 'modules/deploy.bicep' = [for (module, index) in modules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Module-${index}' + params: { + name: module.name + automationAccountName: automationAccount.name + version: module.version + uri: module.uri + location: location + tags: tags + } +}] + +module automationAccount_schedules 'schedules/deploy.bicep' = [for (schedule, index) in schedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Schedule-${index}' + params: { + name: schedule.name + automationAccountName: automationAccount.name + advancedSchedule: contains(schedule, 'advancedSchedule') ? schedule.advancedSchedule : null + scheduleDescription: contains(schedule, 'description') ? schedule.description : '' + expiryTime: contains(schedule, 'expiryTime') ? schedule.expiryTime : '' + frequency: contains(schedule, 'frequency') ? schedule.frequency : 'OneTime' + interval: contains(schedule, 'interval') ? schedule.interval : 0 + startTime: contains(schedule, 'startTime') ? schedule.startTime : '' + timeZone: contains(schedule, 'timeZone') ? schedule.timeZone : '' + } +}] + +module automationAccount_runbooks 'runbooks/deploy.bicep' = [for (runbook, index) in runbooks: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Runbook-${index}' + params: { + name: runbook.name + automationAccountName: automationAccount.name + runbookType: runbook.runbookType + runbookDescription: contains(runbook, 'description') ? runbook.description : '' + uri: contains(runbook, 'uri') ? runbook.uri : '' + version: contains(runbook, 'version') ? runbook.version : '' + location: location + tags: tags + } +}] + +module automationAccount_jobSchedules 'jobSchedules/deploy.bicep' = [for (jobSchedule, index) in jobSchedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-JobSchedule-${index}' + params: { + automationAccountName: automationAccount.name + runbookName: jobSchedule.runbookName + scheduleName: jobSchedule.scheduleName + parameters: contains(jobSchedule, 'parameters') ? jobSchedule.parameters : {} + runOn: contains(jobSchedule, 'runOn') ? jobSchedule.runOn : '' + } + dependsOn: [ + automationAccount_schedules + automationAccount_runbooks + ] +}] + +module automationAccount_variables 'variables/deploy.bicep' = [for (variable, index) in variables: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Variable-${index}' + params: { + automationAccountName: automationAccount.name + name: variable.name + description: contains(variable, 'description') ? variable.description : '' + value: variable.value + isEncrypted: contains(variable, 'isEncrypted') ? variable.isEncrypted : true + } +}] + +module automationAccount_linkedService '.bicep/nested_linkedService.bicep' = if (!empty(linkedWorkspaceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-LinkedService' + params: { + name: 'automation' + logAnalyticsWorkspaceName: last(split(linkedWorkspaceId, '/')) + resourceId: automationAccount.id + tags: tags + } + // This is to support linked services to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup(!empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[2] : subscription().subscriptionId, !empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[4] : resourceGroup().name) +} + +module automationAccount_solutions '.bicep/nested_solution.bicep' = [for (gallerySolution, index) in gallerySolutions: if (!empty(linkedWorkspaceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Solution-${index}' + params: { + name: gallerySolution + location: location + logAnalyticsWorkspaceName: last(split(linkedWorkspaceId, '/')) + } + // This is to support solution to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup(!empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[2] : subscription().subscriptionId, !empty(linkedWorkspaceId) ? split(linkedWorkspaceId, '/')[4] : resourceGroup().name) + dependsOn: [ + automationAccount_linkedService + ] +}] + +module automationAccount_softwareUpdateConfigurations 'softwareUpdateConfigurations/deploy.bicep' = [for (softwareUpdateConfiguration, index) in softwareUpdateConfigurations: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-SwUpdateConfig-${index}' + params: { + name: softwareUpdateConfiguration.name + automationAccountName: automationAccount.name + frequency: softwareUpdateConfiguration.frequency + operatingSystem: softwareUpdateConfiguration.operatingSystem + rebootSetting: softwareUpdateConfiguration.rebootSetting + azureVirtualMachines: contains(softwareUpdateConfiguration, 'azureVirtualMachines') ? softwareUpdateConfiguration.azureVirtualMachines : [] + excludeUpdates: contains(softwareUpdateConfiguration, 'excludeUpdates') ? softwareUpdateConfiguration.excludeUpdates : [] + expiryTime: contains(softwareUpdateConfiguration, 'expiryTime') ? softwareUpdateConfiguration.expiryTime : '' + expiryTimeOffsetMinutes: contains(softwareUpdateConfiguration, 'expiryTimeOffsetMinutes') ? softwareUpdateConfiguration.expiryTimeOffsetMinute : 0 + includeUpdates: contains(softwareUpdateConfiguration, 'includeUpdates') ? softwareUpdateConfiguration.includeUpdates : [] + interval: contains(softwareUpdateConfiguration, 'interval') ? softwareUpdateConfiguration.interval : 1 + isEnabled: contains(softwareUpdateConfiguration, 'isEnabled') ? softwareUpdateConfiguration.isEnabled : true + maintenanceWindow: contains(softwareUpdateConfiguration, 'maintenanceWindow') ? softwareUpdateConfiguration.maintenanceWindow : 'PT2H' + monthDays: contains(softwareUpdateConfiguration, 'monthDays') ? softwareUpdateConfiguration.monthDays : [] + monthlyOccurrences: contains(softwareUpdateConfiguration, 'monthlyOccurrences') ? softwareUpdateConfiguration.monthlyOccurrences : [] + nextRun: contains(softwareUpdateConfiguration, 'nextRun') ? softwareUpdateConfiguration.nextRun : '' + nextRunOffsetMinutes: contains(softwareUpdateConfiguration, 'nextRunOffsetMinutes') ? softwareUpdateConfiguration.nextRunOffsetMinutes : 0 + nonAzureComputerNames: contains(softwareUpdateConfiguration, 'nonAzureComputerNames') ? softwareUpdateConfiguration.nonAzureComputerNames : [] + nonAzureQueries: contains(softwareUpdateConfiguration, 'nonAzureQueries') ? softwareUpdateConfiguration.nonAzureQueries : [] + postTaskParameters: contains(softwareUpdateConfiguration, 'postTaskParameters') ? softwareUpdateConfiguration.postTaskParameters : {} + postTaskSource: contains(softwareUpdateConfiguration, 'postTaskSource') ? softwareUpdateConfiguration.postTaskSource : '' + preTaskParameters: contains(softwareUpdateConfiguration, 'preTaskParameters') ? softwareUpdateConfiguration.preTaskParameters : {} + preTaskSource: contains(softwareUpdateConfiguration, 'preTaskSource') ? softwareUpdateConfiguration.preTaskSource : '' + scheduleDescription: contains(softwareUpdateConfiguration, 'scheduleDescription') ? softwareUpdateConfiguration.scheduleDescription : '' + scopeByLocations: contains(softwareUpdateConfiguration, 'scopeByLocations') ? softwareUpdateConfiguration.scopeByLocations : [] + scopeByResources: contains(softwareUpdateConfiguration, 'scopeByResources') ? softwareUpdateConfiguration.scopeByResources : [ + subscription().id + ] + scopeByTags: contains(softwareUpdateConfiguration, 'scopeByTags') ? softwareUpdateConfiguration.scopeByTags : {} + scopeByTagsOperation: contains(softwareUpdateConfiguration, 'scopeByTagsOperation') ? softwareUpdateConfiguration.scopeByTagsOperation : 'All' + startTime: contains(softwareUpdateConfiguration, 'startTime') ? softwareUpdateConfiguration.startTime : '' + timeZone: contains(softwareUpdateConfiguration, 'timeZone') ? softwareUpdateConfiguration.timeZone : 'UTC' + updateClassifications: contains(softwareUpdateConfiguration, 'updateClassifications') ? softwareUpdateConfiguration.updateClassifications : [ + 'Critical' + 'Security' + ] + weekDays: contains(softwareUpdateConfiguration, 'weekDays') ? softwareUpdateConfiguration.weekDays : [] + } + dependsOn: [ + automationAccount_solutions + ] +}] + +resource automationAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${automationAccount.name}-AutoAccount-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: automationAccount +} + +resource automationAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${automationAccount.name}-AutoAccount-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: automationAccount +} + +module automationAccount_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: automationAccount.id + privateEndpointVnetLocation: !empty(privateEndpoints) ? reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location : 'dummy' + privateEndpointObj: endpoint + tags: tags + } +}] + +module automationAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: automationAccount.id + } +}] + +@description('The name of the deployed automation account') +output name string = automationAccount.name + +@description('The resource ID of the deployed automation account') +output resourceId string = automationAccount.id + +@description('The resource group of the deployed automation account') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(automationAccount.identity, 'principalId') ? automationAccount.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/deploy.bicep new file mode 100644 index 000000000..221b1747a --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/deploy.bicep @@ -0,0 +1,60 @@ +@description('Optional. Name of the Automation Account job schedule. Must be a GUID. If not provided, a new GUID is generated.') +param name string = newGuid() + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@description('Required. The runbook property associated with the entity.') +param runbookName string + +@description('Required. The schedule property associated with the entity.') +param scheduleName string + +@description('Optional. List of job properties.') +param parameters object = {} + +@description('Optional. The hybrid worker group that the scheduled job should run on.') +param runOn string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource jobSchedule 'Microsoft.Automation/automationAccounts/jobSchedules@2020-01-13-preview' = { + name: name + parent: automationAccount + properties: { + parameters: parameters + runbook: { + name: runbookName + } + runOn: !empty(runOn) ? runOn : null + schedule: { + name: scheduleName + } + } +} + +@description('The name of the deployed job schedule') +output name string = jobSchedule.name + +@description('The resource ID of the deployed job schedule') +output resourceId string = jobSchedule.id + +@description('The resource group of the deployed job schedule') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/readme.md new file mode 100644 index 000000000..978e31c29 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/readme.md @@ -0,0 +1,46 @@ +# Automation Account Job Schedules `[Microsoft.Automation/automationAccounts/jobSchedules]` + +This module deploys an Azure Automation Account Job Schedule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/jobSchedules` | 2020-01-13-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `automationAccountName` | string | Name of the parent Automation Account. | +| `runbookName` | string | The runbook property associated with the entity. | +| `scheduleName` | string | The schedule property associated with the entity. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[newGuid()]` | Name of the Automation Account job schedule. Must be a GUID. If not provided, a new GUID is generated. | +| `parameters` | object | `{object}` | List of job properties. | +| `runOn` | string | `''` | The hybrid worker group that the scheduled job should run on. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed job schedule | +| `resourceGroupName` | string | The resource group of the deployed job schedule | +| `resourceId` | string | The resource ID of the deployed job schedule | + +## Template references + +- [Automationaccounts/Jobschedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/jobSchedules) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/jobSchedules/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/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/deploy.bicep new file mode 100644 index 000000000..361307448 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/deploy.bicep @@ -0,0 +1,58 @@ +@description('Required. Name of the Automation Account module.') +param name string + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@description('Required. Module package uri, e.g. https://www.powershellgallery.com/api/v2/package.') +param uri string + +@description('Optional. Module version or specify latest to get the latest version.') +param version string = 'latest' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Automation Account resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource module 'Microsoft.Automation/automationAccounts/modules@2020-01-13-preview' = { + name: name + parent: automationAccount + location: location + tags: tags + properties: { + contentLink: { + uri: version != 'latest' ? '${uri}/${name}/${version}' : '${uri}/${name}' + version: version != 'latest' ? version : null + } + } +} + +@description('The name of the deployed module') +output name string = module.name + +@description('The resource ID of the deployed module') +output resourceId string = module.id + +@description('The resource group of the deployed module') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/readme.md new file mode 100644 index 000000000..5f842a26c --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/readme.md @@ -0,0 +1,63 @@ +# Automation Account Modules `[Microsoft.Automation/automationAccounts/modules]` + +This module deploys an Azure Automation Account Module. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/modules` | 2020-01-13-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `automationAccountName` | string | Name of the parent Automation Account. | +| `name` | string | Name of the Automation Account module. | +| `uri` | string | Module package uri, e.g. https://www.powershellgallery.com/api/v2/package. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `tags` | object | `{object}` | Tags of the Automation Account resource. | +| `version` | string | `'latest'` | Module version or specify latest to get the latest version. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed module | +| `resourceGroupName` | string | The resource group of the deployed module | +| `resourceId` | string | The resource ID of the deployed module | + +## Template references + +- [Automationaccounts/Modules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/modules) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/modules/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/carml/1.0.1/Microsoft.Automation/automationAccounts/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/readme.md new file mode 100644 index 000000000..36673c44c --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/readme.md @@ -0,0 +1,220 @@ +# Automation Accounts `[Microsoft.Automation/automationAccounts]` + +This module deploys an Azure Automation Account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Automation/automationAccounts` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/jobSchedules` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/modules` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/runbooks` | 2019-06-01 | +| `Microsoft.Automation/automationAccounts/schedules` | 2020-01-13-preview | +| `Microsoft.Automation/automationAccounts/softwareUpdateConfigurations` | 2019-06-01 | +| `Microsoft.Automation/automationAccounts/variables` | 2020-01-13-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | 2020-03-01-preview | +| `Microsoft.OperationsManagement/solutions` | 2015-11-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Automation Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[JobLogs, JobStreams, DscNodeStatus]` | `[JobLogs, JobStreams, DscNodeStatus]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `encryptionKeySource` | string | `'Microsoft.Automation'` | `[Microsoft.Automation, Microsoft.Keyvault]` | Encryption Key Source. For security reasons it is recommended to use Microsoft.Keyvault if custom keys are available. | +| `encryptionUserAssignedIdentity` | string | `''` | | User identity used for CMK. If you set encryptionKeySource as Microsoft.Keyvault encryptionUserAssignedIdentity is required. | +| `gallerySolutions` | array | `[]` | | List of gallerySolutions to be created in the linked log analytics workspace | +| `jobSchedules` | _[jobSchedules](jobSchedules/readme.md)_ array | `[]` | | List of jobSchedules to be created in the automation account. | +| `keyName` | string | `''` | | The name of key used to encrypt data. This parameter is needed only if you enable Microsoft.Keyvault as encryptionKeySource. | +| `keyvaultUri` | string | `''` | | The URI of the key vault key used to encrypt data. This parameter is needed only if you enable Microsoft.Keyvault as encryptionKeySource. | +| `keyVersion` | string | `''` | | The key version of the key used to encrypt data. This parameter is needed only if you enable Microsoft.Keyvault as encryptionKeySource. | +| `linkedWorkspaceId` | string | `''` | | ID of the log analytics workspace to be linked to the deployed automation account. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `modules` | _[modules](modules/readme.md)_ array | `[]` | | List of modules to be created in the automation account. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `runbooks` | _[runbooks](runbooks/readme.md)_ array | `[]` | | List of runbooks to be created in the automation account. | +| `schedules` | _[schedules](schedules/readme.md)_ array | `[]` | | List of schedules to be created in the automation account. | +| `skuName` | string | `'Basic'` | `[Free, Basic]` | SKU name of the account. | +| `softwareUpdateConfigurations` | _[softwareUpdateConfigurations](softwareUpdateConfigurations/readme.md)_ array | `[]` | | List of softwareUpdateConfigurations to be created in the automation account | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the Automation Account resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `variables` | _[variables](variables/readme.md)_ array | `[]` | | List of variables to be created in the automation account. | + + +### Parameter Usage: `encryption` +Prerequsites: +- User Assigned Identity for Encryption needs `Get`, `List`, `Wrap` and `Unwrap` permissions on the key. +- User Assigned Identity have to be one of the defined identities in userAssignedIdentities parameter block. +- To use Azure Automation with customer managed keys, both `Soft Delete` and `Do Not Purge` features must be turned on to allow for recovery of keys in case of accidental deletion. + +```json +"encryptionKeySource" : { + "value" : "Microsoft.KeyVault" +}, +"encryptionUserAssignedIdentity": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001" // this identity needs to be one of the identities defined in userAssignedIdentities section +}, +"keyName" : { + "value" : "keyEncryptionKey" +}, +"keyvaultUri" : { + "value" : "https://<>.vault.azure.net/" +}, +"keyVersion" : { + "value" : "aa11b22c1234567890c3608c657cd5a2" +}, + +"userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {}, // same value as 'encryptionUserAssignedIdentity' parameter + ... + } +}, +``` +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +``` +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed automation account | +| `resourceGroupName` | string | The resource group of the deployed automation account | +| `resourceId` | string | The resource ID of the deployed automation account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Automationaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts) +- [Automationaccounts/Jobschedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/jobSchedules) +- [Automationaccounts/Modules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/modules) +- [Automationaccounts/Runbooks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/runbooks) +- [Automationaccounts/Schedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/schedules) +- [Automationaccounts/Softwareupdateconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/softwareUpdateConfigurations) +- [Automationaccounts/Variables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/variables) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Solutions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) +- [Workspaces/Linkedservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-03-01-preview/workspaces/linkedServices) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/deploy.bicep new file mode 100644 index 000000000..e506586e5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/deploy.bicep @@ -0,0 +1,97 @@ +@description('Required. Name of the Automation Account runbook.') +param name string + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@allowed([ + 'Graph' + 'GraphPowerShell' + 'GraphPowerShellWorkflow' + 'PowerShell' + 'PowerShellWorkflow' +]) +@description('Required. The type of the runbook.') +param runbookType string + +@description('Optional. The description of the runbook.') +param runbookDescription string = '' + +@description('Optional. The uri of the runbook content.') +param uri string = '' + +@description('Optional. The version of the runbook content.') +param version string = '' + +@description('Optional. ID of the runbook storage account.') +param scriptStorageAccountId string = '' + +@description('Generated. Time used as a basis for e.g. the schedule start date.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Automation Account resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = if (!empty(scriptStorageAccountId)) { + name: last(split(scriptStorageAccountId, '/')) + scope: resourceGroup(split(scriptStorageAccountId, '/')[2], split(scriptStorageAccountId, '/')[4]) +} + +var publishContentLink = empty(uri) ? null : { + uri: !empty(uri) ? (empty(scriptStorageAccountId) ? uri : '${uri}${storageAccount.listAccountSas('2021-04-01', accountSasProperties).accountSasToken}') : null + version: !empty(version) ? version : null +} + +resource runbook 'Microsoft.Automation/automationAccounts/runbooks@2019-06-01' = { + name: name + parent: automationAccount + location: location + tags: tags + properties: { + runbookType: runbookType + description: runbookDescription + publishContentLink: !empty(uri) ? publishContentLink : null + } +} + +@description('The name of the deployed runbook') +output name string = runbook.name + +@description('The resource ID of the deployed runbook') +output resourceId string = runbook.id + +@description('The resource group of the deployed runbook') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/readme.md new file mode 100644 index 000000000..682fbe368 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/readme.md @@ -0,0 +1,72 @@ +# Automation Account Runbooks `[Microsoft.Automation/automationAccounts/runbooks]` + +This module deploys an Azure Automation Account Runbook. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/runbooks` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | Name of the parent Automation Account. | +| `name` | string | | Name of the Automation Account runbook. | +| `runbookType` | string | `[Graph, GraphPowerShell, GraphPowerShellWorkflow, PowerShell, PowerShellWorkflow]` | The type of the runbook. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `runbookDescription` | string | `''` | The description of the runbook. | +| `sasTokenValidityLength` | string | `'PT8H'` | SAS token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `scriptStorageAccountId` | string | `''` | ID of the runbook storage account. | +| `tags` | object | `{object}` | Tags of the Automation Account resource. | +| `uri` | string | `''` | The uri of the runbook content. | +| `version` | string | `''` | The version of the runbook content. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Time used as a basis for e.g. the schedule start date. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed runbook | +| `resourceGroupName` | string | The resource group of the deployed runbook | +| `resourceId` | string | The resource ID of the deployed runbook | + +## Template references + +- [Automationaccounts/Runbooks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/runbooks) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/runbooks/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/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/deploy.bicep new file mode 100644 index 000000000..aa89f7cce --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/deploy.bicep @@ -0,0 +1,84 @@ +@description('Required. Name of the Automation Account schedule.') +param name string + +@description('Required. Name of the parent Automation Account.') +param automationAccountName string + +@description('Optional. The properties of the create Advanced Schedule.') +@metadata({ + monthDays: 'Days of the month that the job should execute on. Must be between 1 and 31.' + monthlyOccurrences: 'Occurrences of days within a month.' + weekDays: 'Days of the week that the job should execute on.' +}) +param advancedSchedule object = {} + +@description('Optional. The description of the schedule.') +param scheduleDescription string = '' + +@description('Optional. The end time of the schedule.') +param expiryTime string = '' + +@allowed([ + 'Day' + 'Hour' + 'Minute' + 'Month' + 'OneTime' + 'Week' +]) +@description('Optional. The frequency of the schedule.') +param frequency string = 'OneTime' + +@description('Optional. Anything') +param interval int = 0 + +@description('Optional. The start time of the schedule.') +param startTime string = '' + +@description('Optional. The time zone of the schedule.') +param timeZone string = '' + +@description('Generated. Time used as a basis for e.g. the schedule start date.') +param baseTime string = utcNow('u') + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource schedule 'Microsoft.Automation/automationAccounts/schedules@2020-01-13-preview' = { + name: name + parent: automationAccount + properties: { + advancedSchedule: !empty(advancedSchedule) ? advancedSchedule : null + description: !empty(scheduleDescription) ? scheduleDescription : null + expiryTime: !empty(expiryTime) ? expiryTime : null + frequency: !empty(frequency) ? frequency : 'OneTime' + interval: (interval != 0) ? interval : null + startTime: !empty(startTime) ? startTime : dateTimeAdd(baseTime, 'PT10M') + timeZone: !empty(timeZone) ? timeZone : null + } +} + +@description('The name of the deployed schedule') +output name string = schedule.name + +@description('The resource ID of the deployed schedule') +output resourceId string = schedule.id + +@description('The resource group of the deployed schedule') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/readme.md new file mode 100644 index 000000000..107be8f7e --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/readme.md @@ -0,0 +1,54 @@ +# Automation Account Schedules `[Microsoft.Automation/automationAccounts/schedules]` + +This module deploys an Azure Automation Account Schedule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/schedules` | 2020-01-13-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `automationAccountName` | string | Name of the parent Automation Account. | +| `name` | string | Name of the Automation Account schedule. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `advancedSchedule` | object | `{object}` | | The properties of the create Advanced Schedule. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `expiryTime` | string | `''` | | The end time of the schedule. | +| `frequency` | string | `'OneTime'` | `[Day, Hour, Minute, Month, OneTime, Week]` | The frequency of the schedule. | +| `interval` | int | `0` | | Anything | +| `scheduleDescription` | string | `''` | | The description of the schedule. | +| `startTime` | string | `''` | | The start time of the schedule. | +| `timeZone` | string | `''` | | The time zone of the schedule. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Time used as a basis for e.g. the schedule start date. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed schedule | +| `resourceGroupName` | string | The resource group of the deployed schedule | +| `resourceId` | string | The resource ID of the deployed schedule | + +## Template references + +- [Automationaccounts/Schedules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/schedules) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/schedules/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/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/deploy.bicep new file mode 100644 index 000000000..8536be21b --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/deploy.bicep @@ -0,0 +1,273 @@ +@description('Required. The name of the Deployment schedule.') +param name string + +@description('Required. Name of the parent Automation Account') +param automationAccountName string + +@description('Required. The operating system to be configured by the deployment schedule.') +@allowed([ + 'Windows' + 'Linux' +]) +param operatingSystem string + +@description('Required. Reboot setting for the deployment schedule.') +@allowed([ + 'IfRequired' + 'Never' + 'RebootOnly' + 'Always' +]) +param rebootSetting string + +@description('Required. The frequency of the deployment schedule. When using \'Hour\', \'Day\', \'Week\' or \'Month\', an interval needs to be provided.') +@allowed([ + 'OneTime' + 'Hour' + 'Day' + 'Week' + 'Month' +]) +param frequency string + +@description('Optional. Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601') +param maintenanceWindow string = 'PT2H' + +@description('Optional. Update classification included in the deployment schedule.') +@allowed([ + 'Critical' + 'Security' + 'UpdateRollup' + 'FeaturePack' + 'ServicePack' + 'Definition' + 'Tools' + 'Updates' + 'Other' +]) +param updateClassifications array = [ + 'Critical' + 'Security' +] + +@description('Optional. KB numbers or Linux packages excluded in the deployment schedule.') +param excludeUpdates array = [] + +@description('Optional. KB numbers or Linux packages included in the deployment schedule.') +param includeUpdates array = [] + +@description('Optional. Specify the resources to scope the deployment schedule to.') +param scopeByResources array = [ + subscription().id +] + +@description('Optional. Specify tags to which to scope the deployment schedule to.') +param scopeByTags object = {} + +@description('Optional. Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B).') +@allowed([ + 'All' + 'Any' +]) +param scopeByTagsOperation string = 'All' + +@description('Optional. Specify locations to which to scope the deployment schedule to.') +param scopeByLocations array = [] + +@description('Optional. Parameters provided to the task running before the deployment schedule.') +param preTaskParameters object = {} + +@description('Optional. The source of the task running before the deployment schedule.') +param preTaskSource string = '' + +@description('Optional. Parameters provided to the task running after the deployment schedule.') +param postTaskParameters object = {} + +@description('Optional. The source of the task running after the deployment schedule.') +param postTaskSource string = '' + +@description('Optional. The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc.') +@maxValue(100) +param interval int = 1 + +@description('Optional. Enables the deployment schedule.') +param isEnabled bool = true + +@description('Optional. Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID.') +param timeZone string = 'UTC' + +@description('Optional. Array of functions from a Log Analytics workspace, used to scope the deployment schedule.') +param nonAzureQueries array = [] + +@description('Optional. List of azure resource IDs for azure virtual machines in scope for the deployment schedule.') +param azureVirtualMachines array = [] + +@description('Optional. List of names of non-azure machines in scope for the deployment schedule.') +param nonAzureComputerNames array = [] + +@description('Optional. Required when used with frequency \'Week\'. Specified the day of the week to run the deployment schedule.') +@allowed([ + 'Monday' + 'Tuesday' + 'Wednesday' + 'Thursday' + 'Friday' + 'Saturday' + 'Sunday' +]) +param weekDays array = [] + +@description('Optional. Can be used with frequency \'Month\'. Provides the specific days of the month to run the deployment schedule.') +@allowed([ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 +]) +param monthDays array = [] + +@description('Optional. Can be used with frequency \'Month\'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule.') +param monthlyOccurrences array = [] + +@description('Optional. The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00.') +param startTime string = '' + +@description('Optional. The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00') +param expiryTime string = '' + +@description('Optional. The expiry time\'s offset in minutes.') +param expiryTimeOffsetMinutes int = 0 + +@description('Optional. The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00') +param nextRun string = '' + +@description('Optional. The next run\'s offset in minutes.') +param nextRunOffsetMinutes int = 0 + +@description('Optional. The schedules description.') +param scheduleDescription string = '' + +@description('Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule.') +param baseTime string = utcNow('u') + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var updateClassifications_var = '${replace(replace(replace(replace(string(updateClassifications), ',', ', '), '[', ''), ']', ''), '"', '')}' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2020-01-13-preview' existing = { + name: automationAccountName +} + +resource softwareUpdateConfiguration 'Microsoft.Automation/automationAccounts/softwareUpdateConfigurations@2019-06-01' = { + name: name + parent: automationAccount + properties: { + updateConfiguration: { + operatingSystem: operatingSystem + duration: maintenanceWindow + linux: ((operatingSystem == 'Linux') ? { + excludedPackageNameMasks: excludeUpdates + includedPackageNameMasks: includeUpdates + includedPackageClassifications: updateClassifications_var + rebootSetting: rebootSetting + } : null) + windows: ((operatingSystem == 'Windows') ? { + excludedKbNumbers: excludeUpdates + includedKbNumbers: includeUpdates + includedUpdateClassifications: updateClassifications_var + rebootSetting: rebootSetting + } : null) + targets: { + azureQueries: [ + { + scope: scopeByResources + tagSettings: { + tags: scopeByTags + filterOperator: scopeByTagsOperation + } + locations: scopeByLocations + } + ] + nonAzureQueries: nonAzureQueries + } + azureVirtualMachines: azureVirtualMachines + nonAzureComputerNames: nonAzureComputerNames + } + tasks: { + preTask: { + parameters: (empty(preTaskParameters) ? null : preTaskParameters) + source: (empty(preTaskSource) ? null : preTaskSource) + } + postTask: { + parameters: (empty(postTaskParameters) ? null : postTaskParameters) + source: (empty(postTaskSource) ? null : postTaskSource) + } + } + scheduleInfo: { + interval: interval + frequency: frequency + isEnabled: isEnabled + timeZone: timeZone + advancedSchedule: { + weekDays: (empty(weekDays) ? null : weekDays) + monthDays: (empty(monthDays) ? null : monthDays) + monthlyOccurrences: (empty(monthlyOccurrences) ? null : monthlyOccurrences) + } + startTime: (empty(startTime) ? dateTimeAdd(baseTime, 'PT10M') : startTime) + expiryTime: expiryTime + expiryTimeOffsetMinutes: expiryTimeOffsetMinutes + nextRun: nextRun + nextRunOffsetMinutes: nextRunOffsetMinutes + description: scheduleDescription + } + } +} + +@description('The name of the deployed softwareUpdateConfiguration') +output name string = softwareUpdateConfiguration.name + +@description('The resource ID of the deployed softwareUpdateConfiguration') +output resourceId string = softwareUpdateConfiguration.id + +@description('The resource group of the deployed softwareUpdateConfiguration') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/readme.md new file mode 100644 index 000000000..b4537051b --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/readme.md @@ -0,0 +1,122 @@ +# Automation Account Software Update Configurations `[Microsoft.Automation/automationAccounts/softwareUpdateConfigurations]` + +This module deploys an Azure Automation Account Software update Configuration. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/softwareUpdateConfigurations` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `automationAccountName` | string | | Name of the parent Automation Account | +| `frequency` | string | `[OneTime, Hour, Day, Week, Month]` | The frequency of the deployment schedule. When using 'Hour', 'Day', 'Week' or 'Month', an interval needs to be provided. | +| `name` | string | | The name of the Deployment schedule. | +| `operatingSystem` | string | `[Windows, Linux]` | The operating system to be configured by the deployment schedule. | +| `rebootSetting` | string | `[IfRequired, Never, RebootOnly, Always]` | Reboot setting for the deployment schedule. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `azureVirtualMachines` | array | `[]` | | List of azure resource IDs for azure virtual machines in scope for the deployment schedule. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `excludeUpdates` | array | `[]` | | KB numbers or Linux packages excluded in the deployment schedule. | +| `expiryTime` | string | `''` | | The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00 | +| `expiryTimeOffsetMinutes` | int | `0` | | The expiry time's offset in minutes. | +| `includeUpdates` | array | `[]` | | KB numbers or Linux packages included in the deployment schedule. | +| `interval` | int | `1` | | The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc. | +| `isEnabled` | bool | `True` | | Enables the deployment schedule. | +| `maintenanceWindow` | string | `'PT2H'` | | Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601 | +| `monthDays` | array | `[]` | `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]` | Can be used with frequency 'Month'. Provides the specific days of the month to run the deployment schedule. | +| `monthlyOccurrences` | array | `[]` | | Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule. | +| `nextRun` | string | `''` | | The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00 | +| `nextRunOffsetMinutes` | int | `0` | | The next run's offset in minutes. | +| `nonAzureComputerNames` | array | `[]` | | List of names of non-azure machines in scope for the deployment schedule. | +| `nonAzureQueries` | array | `[]` | | Array of functions from a Log Analytics workspace, used to scope the deployment schedule. | +| `postTaskParameters` | object | `{object}` | | Parameters provided to the task running after the deployment schedule. | +| `postTaskSource` | string | `''` | | The source of the task running after the deployment schedule. | +| `preTaskParameters` | object | `{object}` | | Parameters provided to the task running before the deployment schedule. | +| `preTaskSource` | string | `''` | | The source of the task running before the deployment schedule. | +| `scheduleDescription` | string | `''` | | The schedules description. | +| `scopeByLocations` | array | `[]` | | Specify locations to which to scope the deployment schedule to. | +| `scopeByResources` | array | `[[subscription().id]]` | | Specify the resources to scope the deployment schedule to. | +| `scopeByTags` | object | `{object}` | | Specify tags to which to scope the deployment schedule to. | +| `scopeByTagsOperation` | string | `'All'` | `[All, Any]` | Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B). | +| `startTime` | string | `''` | | The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00. | +| `timeZone` | string | `'UTC'` | | Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID. | +| `updateClassifications` | array | `[Critical, Security]` | `[Critical, Security, UpdateRollup, FeaturePack, ServicePack, Definition, Tools, Updates, Other]` | Update classification included in the deployment schedule. | +| `weekDays` | array | `[]` | `[Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]` | Required when used with frequency 'Week'. Specified the day of the week to run the deployment schedule. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule. | + + +### Parameter Usage: `scopeByTags` + +Provide tag keys, with an array of values, filtering in machines that should be included in the deployment schedule. + +| Property name | Type | Possible values | Description | +| :------------ | :---- | :-------------- | :---------- | +| \ | array | string | tag values | + +```json +"scopeByTags": { + "value": { + "Update": [ + "Automatic" + ], + "MaintenanceWindow": [ + "1-Sat-22" + ] + } +} +``` + +### Parameter Usage: `monthlyOccurrences` + +Occurrences of days within a month. + +| Property name | Type | Possible values | Description | +| :------------ | :----- | :------------------------------------------------------------- | :----------------------------------------------------------------------------------- | +| `occurance` | int | 1-5 | Occurrence of the week within the month. Must be between 1 and 5, where 5 is "last". | +| `day` | string | Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday | Day of the occurrence. | + +```json +"monthlyOccurrences": { + "value": [ + { + "occurrence": 1, + "day": "Monday" + }, + { + "occurrence": 2, + "day": "Friday" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed softwareUpdateConfiguration | +| `resourceGroupName` | string | The resource group of the deployed softwareUpdateConfiguration | +| `resourceId` | string | The resource ID of the deployed softwareUpdateConfiguration | + +## Template references + +- [Automationaccounts/Softwareupdateconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/softwareUpdateConfigurations) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/softwareUpdateConfigurations/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/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/deploy.bicep b/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/deploy.bicep new file mode 100644 index 000000000..a5a3db191 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/deploy.bicep @@ -0,0 +1,52 @@ +@sys.description('Required. Name of the parent Automation Account') +param automationAccountName string + +@sys.description('Required. The name of the variable.') +param name string + +@sys.description('Required. The value of the variable.') +param value string + +@sys.description('Optional. The description of the variable.') +param description string = '' + +@sys.description('Optional. If the variable should be encrypted. For security reasons encryption of variables should be enabled') +param isEncrypted bool = true + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2021-06-22' existing = { + name: automationAccountName +} + +resource variable 'Microsoft.Automation/automationAccounts/variables@2020-01-13-preview' = { + name: name + parent: automationAccount + properties: { + description: description + isEncrypted: isEncrypted + value: value + } +} + +@sys.description('The name of the deployed variable') +output name string = variable.name + +@sys.description('The resource ID of the deployed variable') +output resourceId string = variable.id + +@sys.description('The resource group of the deployed variable') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/readme.md b/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/readme.md new file mode 100644 index 000000000..0067fe45b --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/readme.md @@ -0,0 +1,69 @@ +# Automation Account Variables `[Microsoft.Automation/automationAccounts/variables]` + +This module deploys a variable to an Azure Automation Account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/variables` | 2020-01-13-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `automationAccountName` | string | Name of the parent Automation Account | +| `name` | string | The name of the variable. | +| `value` | string | The value of the variable. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description of the variable. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `isEncrypted` | bool | `True` | If the variable should be encrypted. For security reasons encryption of variables should be enabled | + + +### Parameter Usage: `value` + +```json + //Boolean format + "value": { + "value": "false" + } + + //DateTime format + "value": { + "value": "\"\\/Date(1637934042656)\\/\"" + } + + //Integer format + "value": { + "value": "500" + } + + //String format + "value": { + "value": "\"TestString\"" + } +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed variable | +| `resourceGroupName` | string | The resource group of the deployed variable | +| `resourceId` | string | The resource ID of the deployed variable | + +## Template references + +- [Automationaccounts/Variables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Automation/2020-01-13-preview/automationAccounts/variables) diff --git a/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/variables/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/carml/1.0.1/Microsoft.Automation/automationAccounts/version.json b/carml/1.0.1/Microsoft.Automation/automationAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Automation/automationAccounts/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/carml/1.0.1/Microsoft.Batch/batchAccounts/.parameters/parameters.json b/carml/1.0.1/Microsoft.Batch/batchAccounts/.parameters/parameters.json new file mode 100644 index 000000000..340396fc9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Batch/batchAccounts/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azbaweux001" + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Batch/batchAccounts/deploy.bicep b/carml/1.0.1/Microsoft.Batch/batchAccounts/deploy.bicep new file mode 100644 index 000000000..afbe11338 --- /dev/null +++ b/carml/1.0.1/Microsoft.Batch/batchAccounts/deploy.bicep @@ -0,0 +1,124 @@ +@description('Required. Name of the Azure Batch') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ServiceLog' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ServiceLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource batchAccount 'Microsoft.Batch/batchAccounts@2020-09-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource batchAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${batchAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: batchAccount +} + +resource batchAccount_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: batchAccount +} + +@description('The name of the batch account') +output name string = batchAccount.name + +@description('The resource ID of the batch account') +output resourceId string = batchAccount.id + +@description('The resource group the batch account was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Batch/batchAccounts/readme.md b/carml/1.0.1/Microsoft.Batch/batchAccounts/readme.md new file mode 100644 index 000000000..f70bee0d3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Batch/batchAccounts/readme.md @@ -0,0 +1,71 @@ +# Batch Accounts `[Microsoft.Batch/batchAccounts]` + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Batch/batchAccounts` | 2020-09-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Batch | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ServiceLog]` | `[ServiceLog]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the batch account | +| `resourceGroupName` | string | The resource group the batch account was deployed into | +| `resourceId` | string | The resource ID of the batch account | + +## Template references + +- [Batchaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Batch/2020-09-01/batchAccounts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.1/Microsoft.Batch/batchAccounts/version.json b/carml/1.0.1/Microsoft.Batch/batchAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Batch/batchAccounts/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/carml/1.0.1/Microsoft.CognitiveServices/accounts/.bicep/nested_privateEndpoints.bicep b/carml/1.0.1/Microsoft.CognitiveServices/accounts/.bicep/nested_privateEndpoints.bicep new file mode 100644 index 000000000..4e7cd75dc --- /dev/null +++ b/carml/1.0.1/Microsoft.CognitiveServices/accounts/.bicep/nested_privateEndpoints.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpoint object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpoint, 'name') ? (empty(privateEndpoint.name) ? '${privateEndpointResourceName}-${privateEndpoint.service}' : privateEndpoint.name) : '${privateEndpointResourceName}-${privateEndpoint.service}') + subnetResourceId: privateEndpoint.subnetResourceId + service: [ + privateEndpoint.service + ] + privateDnsZoneResourceIds: (contains(privateEndpoint, 'privateDnsZoneResourceIds') ? privateEndpoint.privateDnsZoneResourceIds : []) + customDnsConfigs: (contains(privateEndpoint, 'customDnsConfigs') ? (empty(privateEndpoint.customDnsConfigs) ? null : privateEndpoint.customDnsConfigs) : null) +} + +resource privateEndpoint_resource 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_resource.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.1/Microsoft.CognitiveServices/accounts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.CognitiveServices/accounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..679817ba4 --- /dev/null +++ b/carml/1.0.1/Microsoft.CognitiveServices/accounts/.bicep/nested_rbac.bicep @@ -0,0 +1,70 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Cognitive Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68') + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3') + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f') + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c') + 'Cognitive Services Custom Vision Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73') + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b') + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c') + 'Cognitive Services Face Recognizer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9894cab4-e18a-44aa-828b-cb588cd6f2d7') + 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cb43c632-a144-4ec5-977c-e80c4affc34a') + 'Cognitive Services Metrics Advisor User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3b20f47b-3825-43cb-8114-4bd2201156a8') + 'Cognitive Services QnA Maker Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025') + 'Cognitive Services QnA Maker Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126') + 'Cognitive Services Speech Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0e75ca1e-0464-4b4d-8b93-68208a576181') + 'Cognitive Services Speech User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f2dc8367-1007-4938-bd23-fe263f013447') + 'Cognitive Services User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource account 'Microsoft.CognitiveServices/accounts@2017-04-18' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(account.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: account +}] diff --git a/carml/1.0.1/Microsoft.CognitiveServices/accounts/.parameters/parameters.json b/carml/1.0.1/Microsoft.CognitiveServices/accounts/.parameters/parameters.json new file mode 100644 index 000000000..a7eb9a7d6 --- /dev/null +++ b/carml/1.0.1/Microsoft.CognitiveServices/accounts/.parameters/parameters.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cgs-x-001" + }, + "kind": { + "value": "Face" + }, + "sku": { + "value": "F0" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.CognitiveServices/accounts/deploy.bicep b/carml/1.0.1/Microsoft.CognitiveServices/accounts/deploy.bicep new file mode 100644 index 000000000..fe7cb1e2f --- /dev/null +++ b/carml/1.0.1/Microsoft.CognitiveServices/accounts/deploy.bicep @@ -0,0 +1,281 @@ +@description('Required. The name of Cognitive Services account') +param name string + +@description('Required. Kind of the Cognitive Services. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'sku\' for your Azure region.') +@allowed([ + 'AnomalyDetector' + 'Bing.Autosuggest.v7' + 'Bing.CustomSearch' + 'Bing.EntitySearch' + 'Bing.Search.v7' + 'Bing.SpellCheck.v7' + 'CognitiveServices' + 'ComputerVision' + 'ContentModerator' + 'CustomVision.Prediction' + 'CustomVision.Training' + 'Face' + 'FormRecognizer' + 'ImmersiveReader' + 'Internal.AllInOne' + 'LUIS' + 'LUIS.Authoring' + 'Personalizer' + 'QnAMaker' + 'SpeechServices' + 'TextAnalytics' + 'TextTranslation' +]) +param kind string + +@description('Optional. SKU of the Cognitive Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'sku\' for your Azure region.') +@allowed([ + 'C2' + 'C3' + 'C4' + 'F0' + 'F1' + 'S' + 'S0' + 'S1' + 'S10' + 'S2' + 'S3' + 'S4' + 'S5' + 'S6' + 'S7' + 'S8' + 'S9' +]) +param sku string = 'S0' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Subdomain name used for token-based authentication. Required if \'networkAcls\' are set.') +param customSubDomainName string = '' + +@description('Optional. Subdomain name used for token-based authentication. Must be set if \'networkAcls\' are set.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Service endpoint object information') +param networkAcls object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. List of allowed FQDN.') +param allowedFqdnList array = [] + +@description('Optional. The API properties for special APIs.') +param apiProperties object = {} + +@description('Optional. Allow only Azure AD authentication.') +param disableLocalAuth bool = false + +@description('Optional. Properties to configure encryption') +param encryption object = {} + +@description('Optional. Resource migration token.') +param migrationToken string = '' + +@description('Optional. Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists.') +param restore bool = false + +@description('Optional. Restrict outbound network access.') +param restrictOutboundNetworkAccess bool = true + +@description('Optional. The storage accounts for this resource.') +param userOwnedStorage array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Audit' + 'RequestResponse' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Audit' + 'RequestResponse' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var networkAcls_var = { + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: !empty(networkAcls) ? ((length(networkAcls.virtualNetworkRules) == 0) ? [] : networkAcls.virtualNetworkRules) : null + ipRules: !empty(networkAcls) ? ((length(networkAcls.ipRules) == 0) ? [] : networkAcls.ipRules) : null +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource cognitiveServices 'Microsoft.CognitiveServices/accounts@2021-10-01' = { + name: name + kind: kind + identity: identity + location: location + tags: tags + sku: { + name: sku + } + properties: { + customSubDomainName: !empty(customSubDomainName) ? customSubDomainName : null + networkAcls: !empty(networkAcls) ? networkAcls_var : null + publicNetworkAccess: publicNetworkAccess + allowedFqdnList: allowedFqdnList + apiProperties: apiProperties + disableLocalAuth: disableLocalAuth + encryption: !empty(encryption) ? encryption : null + migrationToken: !empty(migrationToken) ? migrationToken : null + restore: restore + restrictOutboundNetworkAccess: restrictOutboundNetworkAccess + userOwnedStorage: !empty(userOwnedStorage) ? userOwnedStorage : null + } +} + +resource cognitiveServices_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${cognitiveServices.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: cognitiveServices +} + +resource cognitiveServices_diagnosticSettingName 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: cognitiveServices +} + +module cognitiveServices_privateEndpoints '.bicep/nested_privateEndpoints.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-CognitiveServices-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: cognitiveServices.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpoint: privateEndpoint + tags: tags + } +}] + +module cognitiveServices_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-CognitiveServices-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: cognitiveServices.id + } +}] + +@description('The name of the cognitive services account') +output name string = cognitiveServices.name + +@description('The resource ID of the cognitive services account') +output resourceId string = cognitiveServices.id + +@description('The resource group the cognitive services account was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The service endpoint of the cognitive services account') +output endpoint string = cognitiveServices.properties.endpoint + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(cognitiveServices.identity, 'principalId') ? cognitiveServices.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.CognitiveServices/accounts/readme.md b/carml/1.0.1/Microsoft.CognitiveServices/accounts/readme.md new file mode 100644 index 000000000..3088889c8 --- /dev/null +++ b/carml/1.0.1/Microsoft.CognitiveServices/accounts/readme.md @@ -0,0 +1,203 @@ +# Cognitive Services `[Microsoft.CognitiveServices/accounts]` + +This module deploys different kinds of cognitive services resources + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.CognitiveServices/accounts` | 2021-10-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `kind` | string | `[AnomalyDetector, Bing.Autosuggest.v7, Bing.CustomSearch, Bing.EntitySearch, Bing.Search.v7, Bing.SpellCheck.v7, CognitiveServices, ComputerVision, ContentModerator, CustomVision.Prediction, CustomVision.Training, Face, FormRecognizer, ImmersiveReader, Internal.AllInOne, LUIS, LUIS.Authoring, Personalizer, QnAMaker, SpeechServices, TextAnalytics, TextTranslation]` | Kind of the Cognitive Services. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'sku' for your Azure region. | +| `name` | string | | The name of Cognitive Services account | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowedFqdnList` | array | `[]` | | List of allowed FQDN. | +| `apiProperties` | object | `{object}` | | The API properties for special APIs. | +| `customSubDomainName` | string | `''` | | Subdomain name used for token-based authentication. Required if 'networkAcls' are set. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Audit, RequestResponse]` | `[Audit, RequestResponse]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disableLocalAuth` | bool | `False` | | Allow only Azure AD authentication. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `encryption` | object | `{object}` | | Properties to configure encryption | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `migrationToken` | string | `''` | | Resource migration token. | +| `networkAcls` | object | `{object}` | | Service endpoint object information | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `publicNetworkAccess` | string | `'Enabled'` | `[Enabled, Disabled]` | Subdomain name used for token-based authentication. Must be set if 'networkAcls' are set. | +| `restore` | bool | `False` | | Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists. | +| `restrictOutboundNetworkAccess` | bool | `True` | | Restrict outbound network access. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'S0'` | `[C2, C3, C4, F0, F1, S, S0, S1, S10, S2, S3, S4, S5, S6, S7, S8, S9]` | SKU of the Cognitive Services resource. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'sku' for your Azure region. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `userOwnedStorage` | array | `[]` | | The storage accounts for this resource. | + + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "id": "/subscriptions//resourceGroups/resourceGroup/providers/Microsoft.Network/virtualNetworks//subnets/", + "ignoreMissingVnetServiceEndpoint": false + } + ], + "ipRules": [ + { + "value": "1.1.1.1" + }, + { + "value": "" + } + ] + } +}, +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `endpoint` | string | The service endpoint of the cognitive services account | +| `name` | string | The name of the cognitive services account | +| `resourceGroupName` | string | The resource group the cognitive services account was deployed into | +| `resourceId` | string | The resource ID of the cognitive services account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +- Not all combinations of parameters `kind` and `sku` are valid and they may vary in different Azure Regions. Please use PowerShell CmdLet `Get-AzCognitiveServicesAccountSku` or another methods to determine valid values in your region. +- Not all kinds of Cognitive Services support virtual networks. Please visit the link below to determine supported services. + +## Template references + +- [Accounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.CognitiveServices/2021-10-01/accounts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.CognitiveServices/accounts/version.json b/carml/1.0.1/Microsoft.CognitiveServices/accounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.CognitiveServices/accounts/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/carml/1.0.1/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ad9e1c7ba --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource availabilitySet 'Microsoft.Compute/availabilitySets@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(availabilitySet.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: availabilitySet +}] diff --git a/carml/1.0.1/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json new file mode 100644 index 000000000..99d2414f7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avs-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/availabilitySets/.parameters/parameters.json b/carml/1.0.1/Microsoft.Compute/availabilitySets/.parameters/parameters.json new file mode 100644 index 000000000..cfa2eab50 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/availabilitySets/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avs-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "proximityPlacementGroupId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/proximityPlacementGroups/adp-<>-az-ppg-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/availabilitySets/deploy.bicep b/carml/1.0.1/Microsoft.Compute/availabilitySets/deploy.bicep new file mode 100644 index 000000000..89ee09731 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/availabilitySets/deploy.bicep @@ -0,0 +1,94 @@ +@description('Required. The name of the availability set that is being created.') +param name string + +@description('Optional. The number of fault domains to use.') +param availabilitySetFaultDomain int = 2 + +@description('Optional. The number of update domains to use.') +param availabilitySetUpdateDomain int = 5 + +@description('''Optional. SKU of the availability set. +- Use \'Aligned\' for virtual machines with managed disks +- Use \'Classic\' for virtual machines with unmanaged disks. +''') +param availabilitySetSku string = 'Aligned' + +@description('Optional. Resource ID of a proximity placement group.') +param proximityPlacementGroupId string = '' + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource availabilitySet 'Microsoft.Compute/availabilitySets@2021-07-01' = { + name: name + location: location + tags: tags + properties: { + platformFaultDomainCount: availabilitySetFaultDomain + platformUpdateDomainCount: availabilitySetUpdateDomain + proximityPlacementGroup: !empty(proximityPlacementGroupId) ? { + id: proximityPlacementGroupId + } : null + } + sku: { + name: availabilitySetSku + } +} + +resource availabilitySet_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${availabilitySet.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: availabilitySet +} + +module availabilitySet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AvSet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: availabilitySet.id + } +}] + +@description('The name of the availability set') +output name string = availabilitySet.name + +@description('The resource ID of the availability set') +output resourceId string = availabilitySet.id + +@description('The resource group the availability set was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Compute/availabilitySets/readme.md b/carml/1.0.1/Microsoft.Compute/availabilitySets/readme.md new file mode 100644 index 000000000..b4b14af26 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/availabilitySets/readme.md @@ -0,0 +1,96 @@ +# Availability Sets `[Microsoft.Compute/availabilitySets]` + +This template deploys an availability set + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/availabilitySets` | 2021-07-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the availability set that is being created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `availabilitySetFaultDomain` | int | `2` | | The number of fault domains to use. | +| `availabilitySetSku` | string | `'Aligned'` | | SKU of the availability set.

    - Use \'Aligned\' for virtual machines with managed disks

    - Use \'Classic\' for virtual machines with unmanaged disks.

    | +| `availabilitySetUpdateDomain` | int | `5` | | The number of update domains to use. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `proximityPlacementGroupId` | string | `''` | | Resource ID of a proximity placement group. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the availability set resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the availability set | +| `resourceGroupName` | string | The resource group the availability set was deployed into | +| `resourceId` | string | The resource ID of the availability set | + +## Template references + +- [Availabilitysets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/availabilitySets) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Compute/availabilitySets/version.json b/carml/1.0.1/Microsoft.Compute/availabilitySets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/availabilitySets/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/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep new file mode 100644 index 000000000..64765196a --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep @@ -0,0 +1,36 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. The access policy name') +param name string = 'add' + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the access policies assignment') +output name string = policies.name + +@description('The resource ID of the access policies assignment') +output resourceId string = policies.id diff --git a/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ba4152534 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(diskEncryptionSet.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: diskEncryptionSet +}] diff --git a/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json new file mode 100644 index 000000000..9ad9ed7c5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-des-x-001" + }, + "keyVaultId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "keyUrl": { + "value": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5" // ID must be updated for new keys + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/deploy.bicep b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/deploy.bicep new file mode 100644 index 000000000..6be6e1972 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/deploy.bicep @@ -0,0 +1,111 @@ +@description('Required. The name of the disk encryption set that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@description('Required. Resource ID of the KeyVault containing the key or secret.') +param keyVaultId string + +@description('Required. Key URL (with version) pointing to a key or secret in KeyVault.') +param keyUrl string + +@description('Optional. The type of key used to encrypt the data of the disk. For security reasons, it is recommended to set encryptionType to EncryptionAtRestWithPlatformAndCustomerKeys') +@allowed([ + 'EncryptionAtRestWithCustomerKey' + 'EncryptionAtRestWithPlatformAndCustomerKeys' +]) +param encryptionType string = 'EncryptionAtRestWithPlatformAndCustomerKeys' + +@description('Optional. Set this flag to true to enable auto-updating of this disk encryption set to the latest key version.') +param rotationToLatestKeyVersionEnabled bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the disk encryption resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + activeKey: { + sourceVault: { + id: keyVaultId + } + keyUrl: keyUrl + } + encryptionType: encryptionType + rotationToLatestKeyVersionEnabled: rotationToLatestKeyVersionEnabled + } +} + +module keyVaultAccessPolicies '.bicep/nested_kvAccessPolicy.bicep' = { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-KVAccessPolicies' + params: { + keyVaultName: last(split(keyVaultId, '/')) + accessPolicies: [ + { + tenantId: subscription().tenantId + objectId: diskEncryptionSet.identity.principalId + permissions: { + keys: [ + 'get' + 'wrapKey' + 'unwrapKey' + ] + secrets: [] + certificates: [] + } + } + ] + } + // This is to support access policies to KV in different subscription and resource group than the disk encryption set. + scope: resourceGroup(split(keyVaultId, '/')[2], split(keyVaultId, '/')[4]) +} + +module diskEncryptionSet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: diskEncryptionSet.id + } +}] + +@description('The resource ID of the disk encryption set') +output resourceId string = diskEncryptionSet.id + +@description('The name of the disk encryption set') +output name string = diskEncryptionSet.name + +@description('The resource group the disk encryption set was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the disk encryption set') +output systemAssignedPrincipalId string = diskEncryptionSet.identity.principalId + +@description('The name of the key vault with the disk encryption key') +output keyVaultName string = last(split(keyVaultId, '/')) diff --git a/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/readme.md b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/readme.md new file mode 100644 index 000000000..a5c33b0f1 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/readme.md @@ -0,0 +1,97 @@ +# Disk Encryption Sets `[Microsoft.Compute/diskEncryptionSets]` + +This template deploys a disk encryption set. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/diskEncryptionSets` | 2021-04-01 | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyUrl` | string | Key URL (with version) pointing to a key or secret in KeyVault. | +| `keyVaultId` | string | Resource ID of the KeyVault containing the key or secret. | +| `name` | string | The name of the disk encryption set that is being created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `encryptionType` | string | `'EncryptionAtRestWithPlatformAndCustomerKeys'` | `[EncryptionAtRestWithCustomerKey, EncryptionAtRestWithPlatformAndCustomerKeys]` | The type of key used to encrypt the data of the disk. For security reasons, it is recommended to set encryptionType to EncryptionAtRestWithPlatformAndCustomerKeys | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `rotationToLatestKeyVersionEnabled` | bool | `False` | | Set this flag to true to enable auto-updating of this disk encryption set to the latest key version. | +| `tags` | object | `{object}` | | Tags of the disk encryption resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault with the disk encryption key | +| `name` | string | The name of the disk encryption set | +| `resourceGroupName` | string | The resource group the disk encryption set was deployed into | +| `resourceId` | string | The resource ID of the disk encryption set | +| `systemAssignedPrincipalId` | string | The principal ID of the disk encryption set | + +## Template references + +- [Diskencryptionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/diskEncryptionSets) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/version.json b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/diskEncryptionSets/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/carml/1.0.1/Microsoft.Compute/disks/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/disks/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..27a1374a5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource disk 'Microsoft.Compute/disks@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(disk.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: disk +}] diff --git a/carml/1.0.1/Microsoft.Compute/disks/.parameters/image.parameters.json b/carml/1.0.1/Microsoft.Compute/disks/.parameters/image.parameters.json new file mode 100644 index 000000000..d6934ac64 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/.parameters/image.parameters.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-image-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "createOption": { + "value": "FromImage" + }, + "imageReferenceId": { + "value": "/Subscriptions/<>/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2016-Datacenter/Versions/14393.4906.2112080838" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/disks/.parameters/import.parameters.json b/carml/1.0.1/Microsoft.Compute/disks/.parameters/import.parameters.json new file mode 100644 index 000000000..a09908e11 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/.parameters/import.parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-import-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "createOption": { + "value": "Import" + }, + "sourceUri": { + "value": "https://adp<>azsax001.blob.core.windows.net/vhds/adp-<>-az-imgt-x-001.vhd" + }, + "storageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/disks/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Compute/disks/.parameters/min.parameters.json new file mode 100644 index 000000000..d19f33a37 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/.parameters/min.parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-min-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "diskSizeGB": { + "value": 1 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/disks/.parameters/parameters.json b/carml/1.0.1/Microsoft.Compute/disks/.parameters/parameters.json new file mode 100644 index 000000000..3608893d9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-x-001" + }, + "sku": { + "value": "UltraSSD_LRS" + }, + "diskSizeGB": { + "value": 128 + }, + "logicalSectorSize": { + "value": 512 + }, + "diskIOPSReadWrite": { + "value": 500 + }, + "diskMBpsReadWrite": { + "value": 60 + }, + "osType": { + "value": "Windows" + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/disks/deploy.bicep b/carml/1.0.1/Microsoft.Compute/disks/deploy.bicep new file mode 100644 index 000000000..463e0069d --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. The name of the disk that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'Standard_LRS' + 'Premium_LRS' + 'StandardSSD_LRS' + 'UltraSSD_LRS' + 'Premium_ZRS' + 'Premium_ZRS' +]) +@description('Required. The disks sku name. Can be .') +param sku string + +@description('Optional. Set to true to enable bursting beyond the provisioned performance target of the disk.') +param burstingEnabled bool = false + +@description('Optional. Percentage complete for the background copy when a resource is created via the CopyStart operation.') +param completionPercent int = 100 + +@allowed([ + 'Attach' + 'Copy' + 'CopyStart' + 'Empty' + 'FromImage' + 'Import' + 'ImportSecure' + 'Restore' + 'Upload' + 'UploadPreparedSecure' +]) +@description('Optional. Sources of a disk creation.') +param createOption string = 'Empty' + +@description('Optional. A relative uri containing either a Platform Image Repository or user image reference.') +param imageReferenceId string = '' + +@description('Optional. Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096.') +param logicalSectorSize int = 4096 + +@description('Optional. If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state.') +param securityDataUri string = '' + +@description('Optional. If create option is Copy, this is the ARM id of the source snapshot or disk.') +param sourceResourceId string = '' + +@description('Optional. If create option is Import, this is the URI of a blob to be imported into a managed disk.') +param sourceUri string = '' + +@description('Optional. Required if create option is Import. The Azure Resource Manager identifier of the storage account containing the blob to import as a disk') +param storageAccountId string = '' + +@description('Optional. If create option is Upload, this is the size of the contents of the upload including the VHD footer.') +param uploadSizeBytes int = 20972032 + +@description('Optional. If create option is empty, this field is mandatory and it indicates the size of the disk to create.') +param diskSizeGB int = 0 + +@description('Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks.') +param diskIOPSReadWrite int = 0 + +@description('Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks.') +param diskMBpsReadWrite int = 0 + +@allowed([ + 'V1' + 'V2' +]) +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only.') +param hyperVGeneration string = 'V2' + +@description('Optional. The maximum number of VMs that can attach to the disk at the same time. Default value is 0.') +param maxShares int = 1 + +@allowed([ + 'AllowAll' + 'AllowPrivate' + 'DenyAll' +]) +@description('Optional. Policy for accessing the disk via network.') +param networkAccessPolicy string = 'DenyAll' + +@allowed([ + 'Windows' + 'Linux' + '' +]) +@description('Optional. Sources of a disk creation.') +param osType string = '' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Policy for controlling export on the disk.') +param publicNetworkAccess string = 'Disabled' + +@description('Optional. True if the image from which the OS disk is created supports accelerated networking.') +param acceleratedNetwork bool = false + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource disk 'Microsoft.Compute/disks@2021-08-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + } + properties: { + burstingEnabled: burstingEnabled + completionPercent: completionPercent + creationData: { + createOption: createOption + imageReference: createOption != 'FromImage' ? null : { + id: imageReferenceId + } + logicalSectorSize: contains(sku, 'Ultra') ? logicalSectorSize : null + securityDataUri: createOption == 'ImportSecure' ? securityDataUri : null + sourceResourceId: createOption == 'Copy' ? sourceResourceId : null + sourceUri: createOption == 'Import' ? sourceUri : null + storageAccountId: createOption == 'Import' ? storageAccountId : null + uploadSizeBytes: createOption == 'Upload' ? uploadSizeBytes : null + } + diskIOPSReadWrite: contains(sku, 'Ultra') ? diskIOPSReadWrite : null + diskMBpsReadWrite: contains(sku, 'Ultra') ? diskMBpsReadWrite : null + diskSizeGB: createOption == 'Empty' ? diskSizeGB : null + hyperVGeneration: empty(osType) ? null : hyperVGeneration + maxShares: maxShares + networkAccessPolicy: networkAccessPolicy + osType: empty(osType) ? null : osType + publicNetworkAccess: publicNetworkAccess + supportedCapabilities: empty(osType) ? {} : { + acceleratedNetwork: acceleratedNetwork + } + } +} + +resource disk_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${disk.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: disk +} + +module disk_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AvSet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: disk.id + } +}] + +@description('The resource group the disk was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the disk') +output resourceId string = disk.id + +@description('The name of the disk') +output name string = disk.name diff --git a/carml/1.0.1/Microsoft.Compute/disks/readme.md b/carml/1.0.1/Microsoft.Compute/disks/readme.md new file mode 100644 index 000000000..464b7845f --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/readme.md @@ -0,0 +1,112 @@ +# Compute Disks `[Microsoft.Compute/disks]` + +This template deploys a disk + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/disks` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | | The name of the disk that is being created. | +| `sku` | string | `[Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS, Premium_ZRS, Premium_ZRS]` | The disks sku name. Can be . | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `acceleratedNetwork` | bool | `False` | | True if the image from which the OS disk is created supports accelerated networking. | +| `burstingEnabled` | bool | `False` | | Set to true to enable bursting beyond the provisioned performance target of the disk. | +| `completionPercent` | int | `100` | | Percentage complete for the background copy when a resource is created via the CopyStart operation. | +| `createOption` | string | `'Empty'` | `[Attach, Copy, CopyStart, Empty, FromImage, Import, ImportSecure, Restore, Upload, UploadPreparedSecure]` | Sources of a disk creation. | +| `diskIOPSReadWrite` | int | `0` | | The number of IOPS allowed for this disk; only settable for UltraSSD disks. | +| `diskMBpsReadWrite` | int | `0` | | The bandwidth allowed for this disk; only settable for UltraSSD disks. | +| `diskSizeGB` | int | `0` | | If create option is empty, this field is mandatory and it indicates the size of the disk to create. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hyperVGeneration` | string | `'V2'` | `[V1, V2]` | The hypervisor generation of the Virtual Machine. Applicable to OS disks only. | +| `imageReferenceId` | string | `''` | | A relative uri containing either a Platform Image Repository or user image reference. | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `logicalSectorSize` | int | `4096` | | Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096. | +| `maxShares` | int | `1` | | The maximum number of VMs that can attach to the disk at the same time. Default value is 0. | +| `networkAccessPolicy` | string | `'DenyAll'` | `[AllowAll, AllowPrivate, DenyAll]` | Policy for accessing the disk via network. | +| `osType` | string | `''` | `[Windows, Linux, ]` | Sources of a disk creation. | +| `publicNetworkAccess` | string | `'Disabled'` | `[Disabled, Enabled]` | Policy for controlling export on the disk. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityDataUri` | string | `''` | | If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state. | +| `sourceResourceId` | string | `''` | | If create option is Copy, this is the ARM id of the source snapshot or disk. | +| `sourceUri` | string | `''` | | If create option is Import, this is the URI of a blob to be imported into a managed disk. | +| `storageAccountId` | string | `''` | | Required if create option is Import. The Azure Resource Manager identifier of the storage account containing the blob to import as a disk | +| `tags` | object | `{object}` | | Tags of the availability set resource. | +| `uploadSizeBytes` | int | `20972032` | | If create option is Upload, this is the size of the contents of the upload including the VHD footer. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disk | +| `resourceGroupName` | string | The resource group the disk was deployed into | +| `resourceId` | string | The resource ID of the disk | + +## Template references + +- [Disks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-08-01/disks) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Compute/disks/version.json b/carml/1.0.1/Microsoft.Compute/disks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/disks/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/carml/1.0.1/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..1a5646659 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(gallery.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: gallery +}] diff --git a/carml/1.0.1/Microsoft.Compute/galleries/.parameters/images.parameters.json b/carml/1.0.1/Microsoft.Compute/galleries/.parameters/images.parameters.json new file mode 100644 index 000000000..78a802c19 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/.parameters/images.parameters.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsigweuimages001" + }, + "images": { + "value": [ + { + "name": "<>-az-imgd-x-003" + }, + { + "name": "<>-az-imgd-x-001", + "osType": "Windows", + "osState": "Generalized", + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2022-datacenter-azure-edition", + "minRecommendedvCPUs": 2, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "maxRecommendedMemory": 16, + "hyperVGeneration": "V1", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-imgd-x-002", + "osType": "Linux", + "osState": "Generalized", + "publisher": "canonical", + "offer": "0001-com-ubuntu-server-focal", + "sku": "20_04-lts-gen2", + "minRecommendedvCPUs": 1, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "maxRecommendedMemory": 32, + "hyperVGeneration": "V2" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/galleries/.parameters/parameters.json b/carml/1.0.1/Microsoft.Compute/galleries/.parameters/parameters.json new file mode 100644 index 000000000..ccacaf074 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsigweux001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/galleries/deploy.bicep b/carml/1.0.1/Microsoft.Compute/galleries/deploy.bicep new file mode 100644 index 000000000..55f767107 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/deploy.bicep @@ -0,0 +1,110 @@ +@minLength(1) +@description('Required. Name of the Azure Shared Image Gallery') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Description of the Azure Shared Image Gallery') +param galleryDescription string = '' + +@description('Optional. Images to create') +param images array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' = { + name: name + location: location + tags: tags + properties: { + description: galleryDescription + identifier: {} + } +} + +resource gallery_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${gallery.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: gallery +} + +module gallery_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Gallery-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: gallery.id + } +}] + +// Images +module galleries_images 'images/deploy.bicep' = [for (image, index) in images: { + name: '${uniqueString(deployment().name, location)}-Gallery-Image-${index}' + params: { + name: image.name + galleryName: gallery.name + osType: contains(image, 'osType') ? image.osType : 'Windows' + osState: contains(image, 'osState') ? image.osState : 'Generalized' + publisher: contains(image, 'publisher') ? image.publisher : 'MicrosoftWindowsServer' + offer: contains(image, 'offer') ? image.offer : 'WindowsServer' + sku: contains(image, 'sku') ? image.sku : '2019-Datacenter' + minRecommendedvCPUs: contains(image, 'minRecommendedvCPUs') ? image.minRecommendedvCPUs : 1 + maxRecommendedvCPUs: contains(image, 'maxRecommendedvCPUs') ? image.maxRecommendedvCPUs : 4 + minRecommendedMemory: contains(image, 'minRecommendedMemory') ? image.minRecommendedMemory : 4 + maxRecommendedMemory: contains(image, 'maxRecommendedMemory') ? image.maxRecommendedMemory : 16 + hyperVGeneration: contains(image, 'hyperVGeneration') ? image.hyperVGeneration : 'V1' + imageDefinitionDescription: contains(image, 'imageDefinitionDescription') ? image.imageDefinitionDescription : '' + eula: contains(image, 'eula') ? image.eula : '' + privacyStatementUri: contains(image, 'privacyStatementUri') ? image.privacyStatementUri : '' + releaseNoteUri: contains(image, 'releaseNoteUri') ? image.releaseNoteUri : '' + productName: contains(image, 'productName') ? image.productName : '' + planName: contains(image, 'planName') ? image.planName : '' + planPublisherName: contains(image, 'planPublisherName') ? image.planPublisherName : '' + endOfLife: contains(image, 'endOfLife') ? image.endOfLife : '' + excludedDiskTypes: contains(image, 'excludedDiskTypes') ? image.excludedDiskTypes : [] + roleAssignments: contains(image, 'roleAssignments') ? image.roleAssignments : [] + tags: contains(image, 'tags') ? image.tags : {} + } +}] + +@description('The resource ID of the deployed image gallery') +output resourceId string = gallery.id + +@description('The resource group of the deployed image gallery') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed image gallery') +output name string = gallery.name diff --git a/carml/1.0.1/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..927fe6d86 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'myCustomRoleAtSub': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3') +} + +resource galleryImage 'Microsoft.Compute/galleries/images@2020-09-30' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(galleryImage.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: galleryImage +}] diff --git a/carml/1.0.1/Microsoft.Compute/galleries/images/deploy.bicep b/carml/1.0.1/Microsoft.Compute/galleries/images/deploy.bicep new file mode 100644 index 000000000..2de2cd544 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/images/deploy.bicep @@ -0,0 +1,171 @@ +@description('Required. Name of the image definition.') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Name of the Azure Shared Image Gallery') +@minLength(1) +param galleryName string + +@description('Optional. OS type of the image to be created.') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string = 'Windows' + +@description('Optional. This property allows the user to specify whether the virtual machines created under this image are \'Generalized\' or \'Specialized\'.') +@allowed([ + 'Generalized' + 'Specialized' +]) +param osState string = 'Generalized' + +@description('Optional. The name of the gallery Image Definition publisher.') +param publisher string = 'MicrosoftWindowsServer' + +@description('Optional. The name of the gallery Image Definition offer.') +param offer string = 'WindowsServer' + +@description('Optional. The name of the gallery Image Definition SKU.') +param sku string = '2019-Datacenter' + +@description('Optional. The minimum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param minRecommendedvCPUs int = 1 + +@description('Optional. The maximum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param maxRecommendedvCPUs int = 4 + +@description('Optional. The minimum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param minRecommendedMemory int = 4 + +@description('Optional. The maximum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param maxRecommendedMemory int = 16 + +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2') +@allowed([ + 'V1' + 'V2' +]) +param hyperVGeneration string = 'V1' + +@description('Optional. The description of this gallery Image Definition resource. This property is updatable.') +param imageDefinitionDescription string = '' + +@description('Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL.') +param eula string = '' + +@description('Optional. The privacy statement uri. Has to be a valid URL.') +param privacyStatementUri string = '' + +@description('Optional. The release note uri. Has to be a valid URL.') +param releaseNoteUri string = '' + +@description('Optional. The product ID.') +param productName string = '' + +@description('Optional. The plan ID.') +param planName string = '' + +@description('Optional. The publisher ID.') +param planPublisherName string = '' + +@description('Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z') +param endOfLife string = '' + +@description('Optional. List of the excluded disk types. E.g. Standard_LRS') +param excludedDiskTypes array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for all resources.') +param tags object = {} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' existing = { + name: galleryName +} + +resource image 'Microsoft.Compute/galleries/images@2020-09-30' = { + name: name + parent: gallery + location: location + tags: tags + properties: { + osType: osType + osState: osState + identifier: { + publisher: publisher + offer: offer + sku: sku + } + recommended: { + vCPUs: { + min: minRecommendedvCPUs + max: maxRecommendedvCPUs + } + memory: { + min: minRecommendedMemory + max: maxRecommendedMemory + } + } + hyperVGeneration: hyperVGeneration + description: imageDefinitionDescription + eula: eula + privacyStatementUri: privacyStatementUri + releaseNoteUri: releaseNoteUri + purchasePlan: { + product: !empty(productName) ? productName : null + name: !empty(planName) ? planName : null + publisher: !empty(planPublisherName) ? planPublisherName : null + } + endOfLifeDate: endOfLife + disallowed: { + diskTypes: excludedDiskTypes + } + } +} + +module galleryImage_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: image.id + } +}] + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the image') +output resourceId string = image.id + +@description('The name of the image') +output name string = image.name diff --git a/carml/1.0.1/Microsoft.Compute/galleries/images/readme.md b/carml/1.0.1/Microsoft.Compute/galleries/images/readme.md new file mode 100644 index 000000000..a5e3c6399 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/images/readme.md @@ -0,0 +1,109 @@ +# Shared Image Definition `[Microsoft.Compute/galleries/images]` + +This module deploys an Image Definition in a Shared Image Gallery. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/galleries/images` | 2020-09-30 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `galleryName` | string | Name of the Azure Shared Image Gallery | +| `name` | string | Name of the image definition. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endOfLife` | string | `''` | | The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z | +| `eula` | string | `''` | | The Eula agreement for the gallery Image Definition. Has to be a valid URL. | +| `excludedDiskTypes` | array | `[]` | | List of the excluded disk types. E.g. Standard_LRS | +| `hyperVGeneration` | string | `'V1'` | `[V1, V2]` | The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2 | +| `imageDefinitionDescription` | string | `''` | | The description of this gallery Image Definition resource. This property is updatable. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `maxRecommendedMemory` | int | `16` | | The maximum amount of RAM in GB recommended for this image. | +| `maxRecommendedvCPUs` | int | `4` | | The maximum number of the CPU cores recommended for this image. | +| `minRecommendedMemory` | int | `4` | | The minimum amount of RAM in GB recommended for this image. | +| `minRecommendedvCPUs` | int | `1` | | The minimum number of the CPU cores recommended for this image. | +| `offer` | string | `'WindowsServer'` | | The name of the gallery Image Definition offer. | +| `osState` | string | `'Generalized'` | `[Generalized, Specialized]` | This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'. | +| `osType` | string | `'Windows'` | `[Windows, Linux]` | OS type of the image to be created. | +| `planName` | string | `''` | | The plan ID. | +| `planPublisherName` | string | `''` | | The publisher ID. | +| `privacyStatementUri` | string | `''` | | The privacy statement uri. Has to be a valid URL. | +| `productName` | string | `''` | | The product ID. | +| `publisher` | string | `'MicrosoftWindowsServer'` | | The name of the gallery Image Definition publisher. | +| `releaseNoteUri` | string | `''` | | The release note uri. Has to be a valid URL. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'2019-Datacenter'` | | The name of the gallery Image Definition SKU. | +| `tags` | object | `{object}` | | Tags for all resources. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image | +| `resourceGroupName` | string | The resource group the image was deployed into | +| `resourceId` | string | The resource ID of the image | + +## Template references + +- [Galleries/Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries/images) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Compute/galleries/images/version.json b/carml/1.0.1/Microsoft.Compute/galleries/images/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/images/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/carml/1.0.1/Microsoft.Compute/galleries/readme.md b/carml/1.0.1/Microsoft.Compute/galleries/readme.md new file mode 100644 index 000000000..4fc1819d1 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/readme.md @@ -0,0 +1,96 @@ +# Azure Compute Galleries `[Microsoft.Compute/galleries]` + +This module deploys an Azure compute gallery (formerly known as shared image gallery). + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/galleries` | 2020-09-30 | +| `Microsoft.Compute/galleries/images` | 2020-09-30 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Shared Image Gallery | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `galleryDescription` | string | `''` | | Description of the Azure Shared Image Gallery | +| `images` | _[images](images/readme.md)_ array | `[]` | | Images to create | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags for all resources. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed image gallery | +| `resourceGroupName` | string | The resource group of the deployed image gallery | +| `resourceId` | string | The resource ID of the deployed image gallery | + +## Template references + +- [Galleries](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries) +- [Galleries/Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries/images) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Compute/galleries/version.json b/carml/1.0.1/Microsoft.Compute/galleries/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/galleries/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/carml/1.0.1/Microsoft.Compute/images/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/images/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ba00fbee6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/images/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'myCustomRoleAtSub': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3') +} + +resource image 'Microsoft.Compute/images@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(image.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: image +}] diff --git a/carml/1.0.1/Microsoft.Compute/images/.parameters/parameters.json b/carml/1.0.1/Microsoft.Compute/images/.parameters/parameters.json new file mode 100644 index 000000000..85e8b306e --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/images/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-img-x-001" + }, + "osAccountType": { + "value": "Premium_LRS" + }, + "osType": { + "value": "Windows" + }, + "osDiskBlobUri": { + "value": "https://adp<>azsax001.blob.core.windows.net/vhds/adp-<>-az-imgt-x-001.vhd" + }, + "osDiskCaching": { + "value": "ReadWrite" + }, + "zoneResilient": { + "value": true + }, + "hyperVGeneration": { + "value": "V1" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/images/deploy.bicep b/carml/1.0.1/Microsoft.Compute/images/deploy.bicep new file mode 100644 index 000000000..988bbda55 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/images/deploy.bicep @@ -0,0 +1,83 @@ +@description('Required. The name of the image.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The Virtual Hard Disk.') +param osDiskBlobUri string + +@description('Required. This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux') +param osType string + +@description('Optional. Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite') +param osDiskCaching string + +@description('Optional. Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS') +param osAccountType string + +@description('Optional. Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS).') +param zoneResilient bool = false + +@description('Optional. Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2') +param hyperVGeneration string = 'V1' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource image 'Microsoft.Compute/images@2021-04-01' = { + name: name + location: location + tags: tags + properties: { + storageProfile: { + osDisk: { + osType: osType + blobUri: osDiskBlobUri + caching: osDiskCaching + storageAccountType: osAccountType + } + dataDisks: [] + zoneResilient: zoneResilient + } + hyperVGeneration: hyperVGeneration + } +} + +module image_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Image-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: image.id + } +}] + +@description('The resource ID of the image') +output resourceId string = image.id + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image') +output name string = image.name diff --git a/carml/1.0.1/Microsoft.Compute/images/readme.md b/carml/1.0.1/Microsoft.Compute/images/readme.md new file mode 100644 index 000000000..80a46bfbf --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/images/readme.md @@ -0,0 +1,95 @@ +# Images `[Microsoft.Compute/images]` + +This module deploys a compute image. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/images` | 2021-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image. | +| `osDiskBlobUri` | string | The Virtual Hard Disk. | +| `osType` | string | This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hyperVGeneration` | string | `'V1'` | Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2 | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `osAccountType` | string | | Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS | +| `osDiskCaching` | string | | Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | Tags of the resource. | +| `zoneResilient` | bool | `False` | Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS). | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image | +| `resourceGroupName` | string | The resource group the image was deployed into | +| `resourceId` | string | The resource ID of the image | + +## Template references + +- [Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/images) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Compute/images/version.json b/carml/1.0.1/Microsoft.Compute/images/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/images/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/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..0c1d2033e --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(proximityPlacementGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: proximityPlacementGroup +}] diff --git a/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json new file mode 100644 index 000000000..71bff3e25 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ppg-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/deploy.bicep b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/deploy.bicep new file mode 100644 index 000000000..e67aa7740 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/deploy.bicep @@ -0,0 +1,79 @@ +@description('Required. The name of the proximity placement group that is being created.') +param name string = '' + +@description('Optional. Specifies the type of the proximity placement group.') +@allowed([ + 'Standard' + 'Ultra' +]) +param proximityPlacementGroupType string = 'Standard' + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the proximity placement group resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' = { + name: name + location: location + tags: tags + properties: { + proximityPlacementGroupType: proximityPlacementGroupType + } +} + +resource proximityPlacementGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${proximityPlacementGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: proximityPlacementGroup +} + +module proximityPlacementGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ProxPlaceGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: proximityPlacementGroup.id + } +}] + +@description('The name of the proximity placement group') +output name string = proximityPlacementGroup.name + +@description('The resourceId the proximity placement group') +output resourceId string = proximityPlacementGroup.id + +@description('The resource group the proximity placement group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/readme.md b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/readme.md new file mode 100644 index 000000000..4c64d6a1c --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/readme.md @@ -0,0 +1,93 @@ +# Proximity Placement Groups `[Microsoft.Compute/proximityPlacementGroups]` + +This template deploys a proximity placement group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/proximityPlacementGroups` | 2021-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | `''` | The name of the proximity placement group that is being created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `proximityPlacementGroupType` | string | `'Standard'` | `[Standard, Ultra]` | Specifies the type of the proximity placement group. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the proximity placement group resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the proximity placement group | +| `resourceGroupName` | string | The resource group the proximity placement group was deployed into | +| `resourceId` | string | The resourceId the proximity placement group | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Proximityplacementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/proximityPlacementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/version.json b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/proximityPlacementGroups/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/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b9c5776a4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(vmss.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: vmss +}] diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json new file mode 100644 index 000000000..0c3f3189b --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-linux-min-001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "skuName": { + "value": "Standard_B2s" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "adminUsername": { + "value": "scaleSetAdmin" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/scaleSetAdmin/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json new file mode 100644 index 000000000..b4d6340af --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json @@ -0,0 +1,186 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-linux-001" + }, + "vmNamePrefix": { + "value": "vmsslinvm" + }, + "skuName": { + "value": "Standard_B2s" + }, + "skuCapacity": { + "value": 1 + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmPriority": { + "value": "Regular" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "availabilityZones": { + "value": [ + "2" + ] + }, + "scaleSetFaultDomain": { + "value": 1 + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "bootDiagnosticStorageAccountName": { + "value": "adp<>azsax001" + }, + "osType": { + "value": "Linux" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "adminUsername": { + "value": "scaleSetAdmin" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/scaleSetAdmin/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "dataDisks": { + "value": [ + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "sudo apt-get update" + } + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json new file mode 100644 index 000000000..5444ff795 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-win-min-001" + }, + "skuName": { + "value": "Standard_B2s" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "adminUsername": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminUsername" + } + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json new file mode 100644 index 000000000..1fec6b76b --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json @@ -0,0 +1,182 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-win-001" + }, + "vmNamePrefix": { + "value": "vmsswinvm" + }, + "skuName": { + "value": "Standard_B2s" + }, + "skuCapacity": { + "value": 1 + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmPriority": { + "value": "Regular" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "adminUsername": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminUsername" + } + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep new file mode 100644 index 000000000..3d152c277 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep @@ -0,0 +1,661 @@ +@description('Required. Name of the VMSS.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Fault Domain count for each placement group.') +param scaleSetFaultDomain int = 2 + +@description('Optional. Creates an proximity placement group and adds the VMs to it.') +param proximityPlacementGroupName string = '' + +@description('Optional. Specifies the type of the proximity placement group.') +@allowed([ + 'Standard' + 'Ultra' +]) +param proximityPlacementGroupType string = 'Standard' + +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Specifies the mode of an upgrade to virtual machines in the scale set.\' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling') +@allowed([ + 'Manual' + 'Automatic' + 'Rolling' +]) +param upgradePolicyMode string = 'Manual' + +@description('Optional. The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability.') +param maxBatchInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch') +param maxUnhealthyInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch.') +param maxUnhealthyUpgradedInstancePercent int = 20 + +@description('Optional. The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format') +param pauseTimeBetweenBatches string = 'PT0S' + +@description('Optional. Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true.') +param enableAutomaticOSUpgrade bool = false + +@description('Optional. Whether OS image rollback feature should be disabled.') +param disableAutomaticRollback bool = false + +@description('Optional. Specifies whether automatic repairs should be enabled on the virtual machine scale set.') +param automaticRepairsPolicyEnabled bool = false + +@description('Optional. The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M).') +param gracePeriod string = 'PT30M' + +@description('Optional. Specifies the computer name prefix for all of the virtual machines in the scale set.') +@minLength(1) +@maxLength(15) +param vmNamePrefix string = 'vmssvm' + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machines in the scale set.') +param secrets array = [] + +@description('Optional. Specifies Scheduled Event related configurations') +param scheduledEventsProfile object = {} + +@description('Optional. Specifies whether the Virtual Machine Scale Set should be overprovisioned.') +param overprovision bool = false + +@description('Optional. When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs.') +param doNotRunExtensionsOnOverprovisionedVMs bool = false + +@description('Optional. Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage.') +param zoneBalance bool = false + +@description('Optional. When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true.') +param singlePlacementGroup bool = true + +@description('Optional. Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in') +param scaleInPolicy object = { + rules: [ + 'Default' + ] +} + +@description('Required. The SKU size of the VMs.') +param skuName string + +@description('Optional. The initial instance count of scale set VMs.') +param skuCapacity int = 1 + +@description('Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set.') +param availabilityZones array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param publicIpDiagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' = if (!empty(proximityPlacementGroupName)) { + name: !empty(proximityPlacementGroupName) ? proximityPlacementGroupName : 'dummyProximityGroup' + location: location + tags: tags + properties: { + proximityPlacementGroupType: proximityPlacementGroupType + } +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: identity + zones: availabilityZones + properties: { + proximityPlacementGroup: !empty(proximityPlacementGroupName) ? { + id: az.resourceId('Microsoft.Compute/proximityPlacementGroups', proximityPlacementGroup.name) + } : null + upgradePolicy: { + mode: upgradePolicyMode + rollingUpgradePolicy: { + maxBatchInstancePercent: maxBatchInstancePercent + maxUnhealthyInstancePercent: maxUnhealthyInstancePercent + maxUnhealthyUpgradedInstancePercent: maxUnhealthyUpgradedInstancePercent + pauseTimeBetweenBatches: pauseTimeBetweenBatches + } + automaticOSUpgradePolicy: { + enableAutomaticOSUpgrade: enableAutomaticOSUpgrade + disableAutomaticRollback: disableAutomaticRollback + } + } + automaticRepairsPolicy: { + enabled: automaticRepairsPolicyEnabled + gracePeriod: gracePeriod + } + virtualMachineProfile: { + osProfile: { + computerNamePrefix: vmNamePrefix + adminUsername: adminUsername + adminPassword: !empty(adminPassword) ? adminPassword : null + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: secrets + } + securityProfile: { + encryptionAtHost: encryptionAtHost + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + createOption: osDisk.createOption + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : null + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + diffDiskSettings: contains(osDisk, 'diffDiskSettings') ? osDisk.diffDiskSettings : null + osType: contains(osDisk, 'osType') ? osDisk.osType : null + image: contains(osDisk, 'image') ? osDisk.image : null + vhdContainers: contains(osDisk, 'vhdContainers') ? osDisk.vhdContainers : null + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? osDisk.managedDisk.diskEncryptionSet : null + } + } + dataDisks: [for (item, j) in dataDisks: { + lun: j + diskSizeGB: item.diskSizeGB + createOption: item.createOption + caching: item.caching + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + managedDisk: { + storageAccountType: item.managedDisk.storageAccountType + diskEncryptionSet: { + id: enableServerSideEncryption ? item.managedDisk.diskEncryptionSet.id : null + } + } + diskIOPSReadWrite: contains(osDisk, 'diskIOPSReadWrite') ? item.diskIOPSReadWrite : null + diskMBpsReadWrite: contains(osDisk, 'diskMBpsReadWrite') ? item.diskMBpsReadWrite : null + }] + } + networkProfile: { + networkInterfaceConfigurations: [for (nicConfiguration, index) in nicConfigurations: { + name: '${name}${nicConfiguration.nicSuffix}configuration-${index}' + properties: { + primary: (index == 0) ? true : any(null) + enableAcceleratedNetworking: contains(nicConfigurations, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : null + networkSecurityGroup: contains(nicConfigurations, 'nsgId') ? { + id: nicConfiguration.nsgId + } : null + ipConfigurations: nicConfiguration.ipConfigurations + } + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + licenseType: empty(licenseType) ? null : licenseType + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? json('{"maxPrice":"${maxPriceForLowPriorityVm}"}') : null + scheduledEventsProfile: scheduledEventsProfile + } + overprovision: overprovision + doNotRunExtensionsOnOverprovisionedVMs: doNotRunExtensionsOnOverprovisionedVMs + zoneBalance: zoneBalance == 'true' ? zoneBalance : null + platformFaultDomainCount: scaleSetFaultDomain + singlePlacementGroup: singlePlacementGroup + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + scaleInPolicy: scaleInPolicy + } + sku: { + name: skuName + capacity: skuCapacity + } + plan: !empty(plan) ? plan : null +} + +module vmss_domainJoinExtension 'extensions/deploy.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DomainJoin' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + } +} + +module vmss_microsoftAntiMalwareExtension 'extensions/deploy.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftAntiMalware' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + } +} + +resource vmss_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split(monitoringWorkspaceId, '/')) + scope: resourceGroup(split(monitoringWorkspaceId, '/')[2], split(monitoringWorkspaceId, '/')[4]) +} + +module vmss_microsoftMonitoringAgentExtension 'extensions/deploy.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftMonitoringAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftMonitoringAgent' + publisher: 'Microsoft.EnterpriseCloud.Monitoring' + type: osType == 'Windows' ? 'MicrosoftMonitoringAgent' : 'OmsAgentForLinux' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.7') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vmss_logAnalyticsWorkspace.id, vmss_logAnalyticsWorkspace.apiVersion).customerId : '' + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vmss_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + } +} + +module vmss_dependencyAgentExtension 'extensions/deploy.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DependencyAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + } +} + +module vmss_networkWatcherAgentExtension 'extensions/deploy.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-NetworkWatcherAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + } +} + +module vmss_desiredStateConfigurationExtension 'extensions/deploy.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DesiredStateConfiguration' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } +} + +module vmss_customScriptExtension 'extensions/deploy.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-CustomScriptExtension' + params: { + virtualMachineScaleSetName: vmss.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') ? extensionCustomScriptConfig.protectedSettings : {} + } + dependsOn: [ + vmss_desiredStateConfigurationExtension + ] +} + +module vmss_diskEncryptionExtension 'extensions/deploy.bicep' = if (extensionDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DiskEncryption' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionDiskEncryptionConfig, 'typeHandlerVersion') ? extensionDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionDiskEncryptionConfig, 'forceUpdateTag') ? extensionDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionDiskEncryptionConfig.settings + } + dependsOn: [ + vmss_customScriptExtension + vmss_microsoftMonitoringAgentExtension + ] +} + +resource vmss_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vmss.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vmss +} + +resource vmss_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: publicIpDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: vmss +} + +module vmss_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VMSS-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: vmss.id + } +}] + +@description('The resource ID of the virtual machine scale set') +output resourceId string = vmss.id + +@description('The resource group of the virtual machine scale set') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual machine scale set') +output name string = vmss.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(vmss.identity, 'principalId') ? vmss.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep new file mode 100644 index 000000000..c3401b32a --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep @@ -0,0 +1,77 @@ +@description('Required. The name of the virtual machine scale set that extension is provisioned for') +param virtualMachineScaleSetName string + +@description('Required. The name of the virtual machine scale set extension') +param name string + +@description('Required. The name of the extension handler publisher') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension"') +param type string + +@description('Required. Specifies the version of the script handler') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available') +param enableAutomaticUpgrade bool + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualMachineScaleSet 'Microsoft.Compute/virtualMachineScaleSets@2021-07-01' existing = { + name: virtualMachineScaleSetName +} + +resource extension 'Microsoft.Compute/virtualMachineScaleSets/extensions@2021-07-01' = { + name: name + parent: virtualMachineScaleSet + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The ResourceId of the extension') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md new file mode 100644 index 000000000..35ba89baa --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md @@ -0,0 +1,51 @@ +# virtual machine scale set Extensions `[Microsoft.Compute/virtualMachineScaleSets/extensions]` + +This module deploys a virtual machine scale set extension. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | 2021-07-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `autoUpgradeMinorVersion` | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true | +| `enableAutomaticUpgrade` | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available | +| `name` | string | The name of the virtual machine scale set extension | +| `publisher` | string | The name of the extension handler publisher | +| `type` | string | Specifies the type of the extension; an example is "CustomScriptExtension" | +| `typeHandlerVersion` | string | Specifies the version of the script handler | +| `virtualMachineScaleSetName` | string | The name of the virtual machine scale set that extension is provisioned for | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `forceUpdateTag` | string | `''` | How the extension handler should be forced to update even if the extension configuration has not changed | +| `protectedSettings` | secureObject | `{object}` | Any object that contains the extension specific protected settings | +| `settings` | object | `{object}` | Any object that contains the extension specific settings | +| `supressFailures` | bool | `False` | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The ResourceId of the extension | + +## Template references + +- [Virtualmachinescalesets/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachineScaleSets/extensions) diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/version.json b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/extensions/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/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/readme.md b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/readme.md new file mode 100644 index 000000000..1c8157ce9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/readme.md @@ -0,0 +1,443 @@ +# Virtual Machine Scale Sets `[Microsoft.Compute/virtualMachineScaleSets]` + +This module deploys a virtual machine scale set. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/proximityPlacementGroups` | 2021-04-01 | +| `Microsoft.Compute/virtualMachineScaleSets` | 2021-04-01 | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | 2021-07-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.Network/VirtualNetwork` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `adminUsername` | secureString | | Administrator username | +| `imageReference` | object | | OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `name` | string | | Name of the VMSS. | +| `nicConfigurations` | array | | Configures NICs and PIPs. | +| `osDisk` | object | | Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| `osType` | string | `[Windows, Linux]` | The chosen OS type | +| `skuName` | string | | The SKU size of the VMs. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | `''` | | When specifying a Windows Virtual Machine, this value should be passed | +| `automaticRepairsPolicyEnabled` | bool | `False` | | Specifies whether automatic repairs should be enabled on the virtual machine scale set. | +| `availabilityZones` | array | `[]` | | The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set. | +| `bootDiagnosticStorageAccountName` | string | `''` | | Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Storage account boot diagnostic base URI. | +| `customData` | string | `''` | | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disableAutomaticRollback` | bool | `False` | | Whether OS image rollback feature should be disabled. | +| `disablePasswordAuthentication` | bool | `False` | | Specifies whether password authentication should be disabled. | +| `doNotRunExtensionsOnOverprovisionedVMs` | bool | `False` | | When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs. | +| `enableAutomaticOSUpgrade` | bool | `False` | | Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true. | +| `enableAutomaticUpdates` | bool | `True` | | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableEvictionPolicy` | bool | `False` | | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | `False` | | Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. | +| `extensionAntiMalwareConfig` | object | `{object}` | | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDependencyAgentConfig` | object | `{object}` | | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | `''` | | Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `gracePeriod` | string | `'PT30M'` | | The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M). | +| `licenseType` | string | `''` | `[Windows_Client, Windows_Server, ]` | Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxBatchInstancePercent` | int | `20` | | The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability. | +| `maxPriceForLowPriorityVm` | string | `''` | | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `maxUnhealthyInstancePercent` | int | `20` | | The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch | +| `maxUnhealthyUpgradedInstancePercent` | int | `20` | | The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. | +| `monitoringWorkspaceId` | string | `''` | | Resource ID of the monitoring log analytics workspace. | +| `overprovision` | bool | `False` | | Specifies whether the Virtual Machine Scale Set should be overprovisioned. | +| `pauseTimeBetweenBatches` | string | `'PT0S'` | | The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format | +| `plan` | object | `{object}` | | Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | `''` | | Creates an proximity placement group and adds the VMs to it. | +| `proximityPlacementGroupType` | string | `'Standard'` | `[Standard, Ultra]` | Specifies the type of the proximity placement group. | +| `publicIpDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `publicKeys` | array | `[]` | | The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sasTokenValidityLength` | string | `'PT8H'` | | SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `scaleInPolicy` | object | `{object}` | | Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in | +| `scaleSetFaultDomain` | int | `2` | | Fault Domain count for each placement group. | +| `scheduledEventsProfile` | object | `{object}` | | Specifies Scheduled Event related configurations | +| `secrets` | array | `[]` | | Specifies set of certificates that should be installed onto the virtual machines in the scale set. | +| `secureBootEnabled` | bool | `False` | | Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `securityType` | string | `''` | | Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings. | +| `singlePlacementGroup` | bool | `True` | | When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true. | +| `skuCapacity` | int | `1` | | The initial instance count of scale set VMs. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `''` | | Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | `False` | | The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `upgradePolicyMode` | string | `'Manual'` | `[Manual, Automatic, Rolling]` | Specifies the mode of an upgrade to virtual machines in the scale set.' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vmNamePrefix` | string | `'vmssvm'` | | Specifies the computer name prefix for all of the virtual machines in the scale set. | +| `vmPriority` | string | `'Regular'` | `[Regular, Low, Spot]` | Specifies the priority for the virtual machine. | +| `vTpmEnabled` | bool | `False` | | Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | +| `zoneBalance` | bool | `False` | | Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +#### Marketplace images + +```json +"imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } +} +``` + +#### Custom images + +```json +"imageReference": { + "value": { + "id": "/subscriptions/12345-6789-1011-1213-15161718/resourceGroups/rg-name/providers/Microsoft.Compute/images/imagename" + } +} +``` + +### Parameter Usage: `plan` + +```json +"plan": { + "value": { + "name": "qvsa-25", + "product": "qualys-virtual-scanner", + "publisher": "qualysguard" + } +} +``` + +### Parameter Usage: `osDisk` + +```json + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { // Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. + "id": "/subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/" + } + } + } +} +``` + +### Parameter Usage: `dataDisks` + +```json +"dataDisks": { + "value": [{ + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "writeAcceleratorEnabled": true, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "writeAcceleratorEnabled": true, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }] +} +``` + +### Parameter Usage: `nicConfigurations` + +```json +"nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/agents-vmss-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-scaleset/subnets/sxx-az-subnet-scaleset-linux" + } + } + } + ] + } + ] +} +``` + + +### Parameter Usage: `extensionDomainJoinConfig` + + +```json +"windowsScriptExtensionFileData": { + "value": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageAccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageAccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + "secretName": "domainJoinUser-Password" + } +} +``` + +### Parameter Usage: `extensionNetworkWatcherAgentConfig` + +```json +"extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } +} +``` + +### Parameter Usage: `extensionAntiMalwareConfig` + +Only for OSType Windows + +```json +"extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } +} +``` + +### Parameter Usage: `extensionDiskEncryptionConfig` + +```json +"extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://mykeyvault.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionKeyURL": "https://mykeyvault.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", //'RSA-OAEP'/'RSA-OAEP-256'/'RSA1_5' + "VolumeType": "All", //'OS'/'Data'/'All' + "ResizeOSDisk": "false" + } + } +} +``` + +### Parameter Usage: `extensionCustomScriptConfig` + +```json +"extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + //storage account with public container (no SAS token is required) OR other public URL (not a storage account) + { + "uri": "https://github.com/myProject/File3.ps1", + "storageAccountId": "" + } + ], + "settings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File testscript.ps1" + } + } +} +``` + +### Parameter Usage: `extensionDSCConfig` + +```json +"extensionDSCConfig": { + "value": { + { + "enabled": true, + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "http://validURLToConfigLocation", + "script": "ConfigurationScript.ps1", + "function": "ConfigurationFunction" + }, + "configurationArguments": { + "argument1": "Value1", + "argument2": "Value2" + }, + "configurationData": { + "url": "https://foo.psd1" + }, + "privacy": { + "dataCollection": "enable" + }, + "advancedOptions": { + "forcePullAndApply": false, + "downloadMappings": { + "specificDependencyKey": "https://myCustomDependencyLocation" + } + } + }, + "protectedSettings": { + "configurationArguments": { + "mySecret": "MyPlaceholder" + }, + "configurationUrlSasToken": "MyPlaceholder", + "configurationDataUrlSasToken": "MyPlaceholder" + } + } + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual machine scale set | +| `resourceGroupName` | string | The resource group of the virtual machine scale set | +| `resourceId` | string | The resource ID of the virtual machine scale set | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Proximityplacementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/proximityPlacementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualmachinescalesets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/virtualMachineScaleSets) +- [Virtualmachinescalesets/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachineScaleSets/extensions) diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/version.json b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachineScaleSets/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/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep new file mode 100644 index 000000000..7e6865bc6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep @@ -0,0 +1,27 @@ +param backupResourceName string + +@allowed([ + 'AzureFileShareProtectedItem' + 'AzureVmWorkloadSAPAseDatabase' + 'AzureVmWorkloadSAPHanaDatabase' + 'AzureVmWorkloadSQLDatabase' + 'DPMProtectedItem' + 'GenericProtectedItem' + 'MabFileFolderProtectedItem' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'Microsoft.Sql/servers/databases' +]) +param protectedItemType string +param backupPolicyId string +param sourceResourceId string + +resource backup 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2021-06-01' = { + name: backupResourceName + location: resourceGroup().location + properties: { + protectedItemType: protectedItemType + policyId: backupPolicyId + sourceResourceId: sourceResourceId + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep new file mode 100644 index 000000000..35df401f8 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep @@ -0,0 +1,33 @@ +@description('Optional. The name of the configuration profile assignment') +param name string = 'default' + +@description('Required. The name of the VM to be associated') +param virtualMachineName string + +@description('Required. The configuration profile of automanage') +@allowed([ + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' +]) +param configurationProfile string + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: virtualMachineName +} + +resource configurationProfileAssignment 'Microsoft.Automanage/configurationProfileAssignments@2021-04-30-preview' = { + name: name + properties: { + configurationProfile: configurationProfile + } + scope: virtualMachine +} + +@description('The resource ID of the configuration profile assignment') +output resourceId string = configurationProfileAssignment.id + +@description('The name of the configuration profile assignment') +output name string = configurationProfileAssignment.name + +@description('The resource group the configuration profile assignment was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep new file mode 100644 index 000000000..e7b50c9ed --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep @@ -0,0 +1,123 @@ +param networkInterfaceName string +param virtualMachineName string +param location string +param tags object +param enableIPForwarding bool = false +param enableAcceleratedNetworking bool = false +param dnsServers array = [] +param networkSecurityGroupId string = '' +param ipConfigurationArray array +param lock string +param diagnosticStorageAccountId string +param diagnosticLogsRetentionInDays int +param diagnosticWorkspaceId string +param diagnosticEventHubAuthorizationRuleId string +param diagnosticEventHubName string +param pipdiagnosticMetricsToEnable array +param pipdiagnosticLogCategoriesToEnable array +param nicDiagnosticMetricsToEnable array +param roleAssignments array + +@description('Optional. The name of the PIP diagnostic setting, if deployed.') +param pipDiagnosticSettingsName string = '${virtualMachineName}-diagnosticSettings' + +@description('Optional. The name of the NIC diagnostic setting, if deployed.') +param nicDiagnosticSettingsName string = '${virtualMachineName}-diagnosticSettings' + +var nicDiagnosticsMetrics = [for metric in nicDiagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module networkInterface_publicIPConfigurations 'nested_networkInterface_publicIPAddress.bicep' = [for (ipConfiguration, index) in ipConfigurationArray: if (contains(ipConfiguration, 'pipconfiguration')) { + name: '${deployment().name}-PIP-${index}' + params: { + publicIPAddressName: '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}' + publicIPPrefixId: (contains(ipConfiguration.pipconfiguration, 'publicIPPrefixId') ? (!(empty(ipConfiguration.pipconfiguration.publicIPPrefixId)) ? ipConfiguration.pipconfiguration.publicIPPrefixId : '') : '') + publicIPAllocationMethod: (contains(ipConfiguration.pipconfiguration, 'publicIPAllocationMethod') ? (!(empty(ipConfiguration.pipconfiguration.publicIPAllocationMethod)) ? ipConfiguration.pipconfiguration.publicIPAllocationMethod : 'Static') : 'Static') + skuName: (contains(ipConfiguration.pipconfiguration, 'skuName') ? (!(empty(ipConfiguration.pipconfiguration.skuName)) ? ipConfiguration.pipconfiguration.skuName : 'Standard') : 'Standard') + skuTier: (contains(ipConfiguration.pipconfiguration, 'skuTier') ? (!(empty(ipConfiguration.pipconfiguration.skuTier)) ? ipConfiguration.pipconfiguration.skuTier : 'Regional') : 'Regional') + location: location + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + diagnosticSettingsName: pipDiagnosticSettingsName + diagnosticMetricsToEnable: pipdiagnosticMetricsToEnable + diagnosticLogCategoriesToEnable: pipdiagnosticLogCategoriesToEnable + lock: lock + roleAssignments: contains(ipConfiguration.pipconfiguration, 'roleAssignments') ? (!empty(ipConfiguration.pipconfiguration.roleAssignments) ? ipConfiguration.pipconfiguration.roleAssignments : []) : [] + tags: tags + } +}] + +resource networkInterface 'Microsoft.Network/networkInterfaces@2021-05-01' = { + name: networkInterfaceName + location: location + tags: tags + properties: { + enableIPForwarding: enableIPForwarding + enableAcceleratedNetworking: enableAcceleratedNetworking + dnsSettings: !empty(dnsServers) ? { + dnsServers: dnsServers + } : null + networkSecurityGroup: !empty(networkSecurityGroupId) ? { + id: networkSecurityGroupId + } : null + ipConfigurations: [for (ipConfiguration, index) in ipConfigurationArray: { + name: !empty(ipConfiguration.name) ? ipConfiguration.name : null + properties: { + primary: ((index == 0) ? true : false) + privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) : null + privateIPAddress: contains(ipConfiguration, 'vmIPAddress') ? (!empty(ipConfiguration.vmIPAddress) ? ipConfiguration.vmIPAddress : null) : null + publicIPAddress: contains(ipConfiguration, 'pipconfiguration') ? json('{"id":"${resourceId('Microsoft.Network/publicIPAddresses', '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}')}"}') : null + subnet: { + id: ipConfiguration.subnetId + } + loadBalancerBackendAddressPools: contains(ipConfiguration, 'loadBalancerBackendAddressPools') ? ipConfiguration.loadBalancerBackendAddressPools : null + applicationSecurityGroups: contains(ipConfiguration, 'applicationSecurityGroups') ? ipConfiguration.applicationSecurityGroups : null + } + }] + } + dependsOn: [ + networkInterface_publicIPConfigurations + ] +} + +resource networkInterface_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkInterface.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkInterface +} + +resource networkInterface_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: nicDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: nicDiagnosticsMetrics + } + scope: networkInterface +} + +module networkInterface_rbac 'nested_networkInterface_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkInterface.id + } +}] diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep new file mode 100644 index 000000000..d8e3494d4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep @@ -0,0 +1,96 @@ +param publicIPAddressName string +param publicIPPrefixId string +param publicIPAllocationMethod string +param skuName string +param skuTier string +param location string +param diagnosticStorageAccountId string +param diagnosticLogsRetentionInDays int +param diagnosticWorkspaceId string +param diagnosticEventHubAuthorizationRuleId string +param diagnosticEventHubName string +param diagnosticMetricsToEnable array +param diagnosticLogCategoriesToEnable array +param lock string +param roleAssignments array +param tags object + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${publicIPAddressName}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: publicIPAddressName + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + properties: { + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixId) ? { + id: publicIPPrefixId + } : null + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac 'nested_networkInterface_publicIPAddress_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The name of the resource group the public IP address was deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address.') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address.') +output resourceId string = publicIpAddress.id diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep new file mode 100644 index 000000000..87e8e8d34 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpAddress +}] diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep new file mode 100644 index 000000000..76ae1e208 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource networkInterface 'Microsoft.Network/networkInterfaces@2021-03-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkInterface.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: networkInterface +}] diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..700fa4a5b --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualMachine.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualMachine +}] diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json new file mode 100644 index 000000000..2faa09d2f --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-linux-min-01" + }, + "osType": { + "value": "Linux" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + } + } + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json new file mode 100644 index 000000000..8938e6f7a --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json @@ -0,0 +1,220 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-linux-01" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "osType": { + "value": "Linux" + }, + "encryptionAtHost": { + "value": false + }, + "availabilityZone": { + "value": 1 + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "caching": "ReadOnly", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "dataDisks": { + "value": [ + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "ReadWrite", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "ReadWrite", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "loadBalancerBackendAddressPools": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" + } + ], + "applicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ] + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "backupVaultName": { + "value": "adp-<>-az-rsv-x-001" + }, + "backupVaultResourceGroup": { + "value": "validation-rg" + }, + "backupPolicyName": { + "value": "VMpolicy" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "monitoringWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": false + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ] + } + }, + "extensionCustomScriptProtectedSetting": { + "value": { + "commandToExecute": "sudo apt-get update" + } + }, + "configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json new file mode 100644 index 000000000..499379aba --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "adminUsername": { + "value": "localAdminUser" + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + } + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json new file mode 100644 index 000000000..632de7554 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json @@ -0,0 +1,237 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-win-01" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "caching": "None", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "dataDisks": { + "value": [ + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "None", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "None", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "availabilityZone": { + "value": 2 + }, + "adminUsername": { + "value": "localAdminUser" + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "loadBalancerBackendAddressPools": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" + } + ], + "applicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ] + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "backupVaultName": { + "value": "adp-<>-az-rsv-x-001" + }, + "backupVaultResourceGroup": { + "value": "validation-rg" + }, + "backupPolicyName": { + "value": "VMpolicy" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": "true", + "Exclusions": { + "Extensions": ".ext1;.ext2", + "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", + "Processes": "excludedproc1.exe;excludedproc2.exe" + }, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "monitoringWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ] + } + }, + "extensionCustomScriptProtectedSetting": { + "value": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + }, + "configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/deploy.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/deploy.bicep new file mode 100644 index 000000000..a495564b0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/deploy.bicep @@ -0,0 +1,645 @@ +// Main resource +@description('Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group\'s name.') +param name string = take(toLower(uniqueString(resourceGroup().name)), 10) + +@description('Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are \'none\' (Default), \'uppercase\' and \'lowercase\'.') +param vmComputerNamesTransformation string = 'none' + +@description('Required. Specifies the size for the VMs') +param vmSize string + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machine.') +param certificatesToBeInstalled array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies resource ID about the dedicated host that the virtual machine resides in.') +param dedicatedHostId string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Resource name of a proximity placement group.') +param proximityPlacementGroupName string = '' + +@description('Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set.') +param availabilitySetName string = '' + +@description('Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set.') +@allowed([ + 0 + 1 + 2 + 3 +]) +param availabilityZone int = 0 + +// External resources +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array + +@description('Optional. The name of the PIP diagnostic setting, if deployed.') +param pipDiagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param pipdiagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param pipdiagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the NIC diagnostic setting, if deployed.') +param nicDiagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param nicdiagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. Recovery service vault name to add VMs to backup.') +param backupVaultName string = '' + +@description('Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default.') +param backupVaultResourceGroup string = resourceGroup().name + +@description('Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault.') +param backupPolicyName string = 'DefaultPolicy' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +// Child resources +@description('Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine.') +param allowExtensionOperations bool = true + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param extensionCustomScriptProtectedSetting object = {} + +// Shared parameters +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Any VM configuration profile assignments') +param configurationProfileAssignments array = [] + +var vmComputerNameTransformed = vmComputerNamesTransformation == 'uppercase' ? toUpper(name) : (vmComputerNamesTransformation == 'lowercase' ? toLower(name) : name) + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module virtualMachine_nic '.bicep/nested_networkInterface.bicep' = [for (nicConfiguration, index) in nicConfigurations: { + name: '${uniqueString(deployment().name, location)}-VM-Nic-${index}' + params: { + networkInterfaceName: '${name}${nicConfiguration.nicSuffix}' + virtualMachineName: name + location: location + tags: tags + enableIPForwarding: contains(nicConfiguration, 'enableIPForwarding') ? (!empty(nicConfiguration.enableIPForwarding) ? nicConfiguration.enableIPForwarding : false) : false + enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true + dnsServers: contains(nicConfiguration, 'dnsServers') ? (!empty(nicConfiguration.dnsServers) ? nicConfiguration.dnsServers : []) : [] + networkSecurityGroupId: contains(nicConfiguration, 'nsgId') ? (!empty(nicConfiguration.nsgId) ? nicConfiguration.nsgId : '') : '' + ipConfigurationArray: nicConfiguration.ipConfigurations + lock: lock + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + pipDiagnosticSettingsName: pipDiagnosticSettingsName + nicDiagnosticSettingsName: nicDiagnosticSettingsName + pipdiagnosticMetricsToEnable: pipdiagnosticMetricsToEnable + pipdiagnosticLogCategoriesToEnable: pipdiagnosticLogCategoriesToEnable + nicDiagnosticMetricsToEnable: nicdiagnosticMetricsToEnable + roleAssignments: contains(nicConfiguration, 'roleAssignments') ? (!empty(nicConfiguration.roleAssignments) ? nicConfiguration.roleAssignments : []) : [] + } +}] + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' = { + name: name + location: location + identity: identity + tags: tags + zones: availabilityZone != 0 ? array(availabilityZone) : null + plan: !empty(plan) ? plan : null + properties: { + hardwareProfile: { + vmSize: vmSize + } + securityProfile: { + encryptionAtHost: encryptionAtHost ? encryptionAtHost : null + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + name: '${name}-disk-os-01' + createOption: contains(osDisk, 'createOption') ? osDisk.createOption : 'FromImage' + deleteOption: contains(osDisk, 'deleteOption') ? osDisk.deleteOption : 'Delete' + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : 'ReadOnly' + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? osDisk.managedDisk.diskEncryptionSet : null + } + } + dataDisks: [for (dataDisk, index) in dataDisks: { + lun: index + name: '${name}-disk-data-${padLeft((index + 1), 2, '0')}' + diskSizeGB: dataDisk.diskSizeGB + createOption: contains(dataDisk, 'createOption') ? dataDisk.createOption : 'Empty' + deleteOption: contains(dataDisk, 'deleteOption') ? dataDisk.deleteOption : 'Delete' + caching: contains(dataDisk, 'caching') ? dataDisk.caching : 'ReadOnly' + managedDisk: { + storageAccountType: dataDisk.managedDisk.storageAccountType + diskEncryptionSet: { + id: enableServerSideEncryption ? dataDisk.managedDisk.diskEncryptionSet.id : null + } + } + }] + } + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + osProfile: { + computerName: vmComputerNameTransformed + adminUsername: adminUsername + adminPassword: adminPassword + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: certificatesToBeInstalled + allowExtensionOperations: allowExtensionOperations + } + networkProfile: { + networkInterfaces: [for (nicConfiguration, index) in nicConfigurations: { + properties: { + deleteOption: contains(nicConfiguration, 'deleteOption') ? nicConfiguration.deleteOption : 'Delete' + primary: index == 0 ? true : false + } + id: az.resourceId('Microsoft.Network/networkInterfaces', '${name}${nicConfiguration.nicSuffix}') + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + availabilitySet: !empty(availabilitySetName) ? json('{"id":"${az.resourceId('Microsoft.Compute/availabilitySets', availabilitySetName)}"}') : null + proximityPlacementGroup: !empty(proximityPlacementGroupName) ? json('{"id":"${az.resourceId('Microsoft.Compute/proximityPlacementGroups', proximityPlacementGroupName)}"}') : null + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? json('{"maxPrice":"${maxPriceForLowPriorityVm}"}') : null + host: !empty(dedicatedHostId) ? json('{"id":"${dedicatedHostId}"}') : null + licenseType: !empty(licenseType) ? licenseType : null + } + dependsOn: [ + virtualMachine_nic + ] +} + +module vm_configurationProfileAssignment '.bicep/nested_configurationProfileAssignment.bicep' = [for (configurationProfileAssignment, index) in configurationProfileAssignments: { + name: '${uniqueString(deployment().name, location)}-VM-ConfigurationProfileAssignment-${index}' + params: { + virtualMachineName: virtualMachine.name + configurationProfile: configurationProfileAssignment + } +}] + +module vm_domainJoinExtension 'extensions/deploy.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DomainJoin' + params: { + virtualMachineName: virtualMachine.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + } +} + +module vm_microsoftAntiMalwareExtension 'extensions/deploy.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftAntiMalware' + params: { + virtualMachineName: virtualMachine.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + } +} + +resource vm_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split(monitoringWorkspaceId, '/')) + scope: az.resourceGroup(split(monitoringWorkspaceId, '/')[2], split(monitoringWorkspaceId, '/')[4]) +} + +module vm_microsoftMonitoringAgentExtension 'extensions/deploy.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftMonitoringAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'MicrosoftMonitoringAgent' + publisher: 'Microsoft.EnterpriseCloud.Monitoring' + type: osType == 'Windows' ? 'MicrosoftMonitoringAgent' : 'OmsAgentForLinux' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.7') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vm_logAnalyticsWorkspace.id, vm_logAnalyticsWorkspace.apiVersion).customerId : '' + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vm_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + } +} + +module vm_dependencyAgentExtension 'extensions/deploy.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DependencyAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + } +} + +module vm_networkWatcherAgentExtension 'extensions/deploy.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-NetworkWatcherAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + } +} + +module vm_desiredStateConfigurationExtension 'extensions/deploy.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DesiredStateConfiguration' + params: { + virtualMachineName: virtualMachine.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } +} + +module vm_customScriptExtension 'extensions/deploy.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-CustomScriptExtension' + params: { + virtualMachineName: virtualMachine.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: extensionCustomScriptProtectedSetting + } + dependsOn: [ + vm_desiredStateConfigurationExtension + ] +} + +module vm_diskEncryptionExtension 'extensions/deploy.bicep' = if (extensionDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DiskEncryption' + params: { + virtualMachineName: virtualMachine.name + name: 'DiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionDiskEncryptionConfig, 'typeHandlerVersion') ? extensionDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionDiskEncryptionConfig, 'forceUpdateTag') ? extensionDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionDiskEncryptionConfig.settings + } + dependsOn: [ + vm_customScriptExtension + vm_microsoftMonitoringAgentExtension + ] +} + +module virtualMachine_backup '.bicep/nested_backup.bicep' = if (!empty(backupVaultName)) { + name: '${uniqueString(deployment().name, location)}-VM-Backup' + params: { + backupResourceName: '${backupVaultName}/Azure/iaasvmcontainer;iaasvmcontainerv2;${resourceGroup().name};${virtualMachine.name}/vm;iaasvmcontainerv2;${resourceGroup().name};${virtualMachine.name}' + protectedItemType: 'Microsoft.Compute/virtualMachines' + backupPolicyId: az.resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', backupVaultName, backupPolicyName) + sourceResourceId: virtualMachine.id + } + scope: az.resourceGroup(backupVaultResourceGroup) + dependsOn: [ + vm_domainJoinExtension + vm_microsoftMonitoringAgentExtension + vm_microsoftAntiMalwareExtension + vm_networkWatcherAgentExtension + vm_dependencyAgentExtension + vm_desiredStateConfigurationExtension + vm_customScriptExtension + ] +} + +resource virtualMachine_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualMachine.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualMachine +} + +module virtualMachine_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VM-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualMachine.id + } +}] + +@description('The name of the VM.') +output name string = virtualMachine.name + +@description('The resource ID of the VM.') +output resourceId string = virtualMachine.id + +@description('The name of the resource group the VM was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(virtualMachine.identity, 'principalId') ? virtualMachine.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/deploy.bicep b/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/deploy.bicep new file mode 100644 index 000000000..b0ec0ffb4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/deploy.bicep @@ -0,0 +1,81 @@ +@description('Required. The name of the virtual machine that extension is provisioned for') +param virtualMachineName string + +@description('Required. The name of the virtual machine extension') +param name string + +@description('Optional. The location the extension is deployed to') +param location string = resourceGroup().location + +@description('Required. The name of the extension handler publisher') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension"') +param type string + +@description('Required. Specifies the version of the script handler') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available') +param enableAutomaticUpgrade bool + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: virtualMachineName +} + +resource extension 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: name + parent: virtualMachine + location: location + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The resource ID of the extension') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/readme.md b/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/readme.md new file mode 100644 index 000000000..77341a1ef --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/readme.md @@ -0,0 +1,52 @@ +# Virtual Machine Extensions `[Microsoft.Compute/virtualMachines/extensions]` + +This module deploys a virtual machine extension. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachines/extensions` | 2021-07-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `autoUpgradeMinorVersion` | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true | +| `enableAutomaticUpgrade` | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available | +| `name` | string | The name of the virtual machine extension | +| `publisher` | string | The name of the extension handler publisher | +| `type` | string | Specifies the type of the extension; an example is "CustomScriptExtension" | +| `typeHandlerVersion` | string | Specifies the version of the script handler | +| `virtualMachineName` | string | The name of the virtual machine that extension is provisioned for | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `forceUpdateTag` | string | `''` | How the extension handler should be forced to update even if the extension configuration has not changed | +| `location` | string | `[resourceGroup().location]` | The location the extension is deployed to | +| `protectedSettings` | secureObject | `{object}` | Any object that contains the extension specific protected settings | +| `settings` | object | `{object}` | Any object that contains the extension specific settings | +| `supressFailures` | bool | `False` | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The resource ID of the extension | + +## Template references + +- [Virtualmachines/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/version.json b/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/extensions/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/carml/1.0.1/Microsoft.Compute/virtualMachines/readme.md b/carml/1.0.1/Microsoft.Compute/virtualMachines/readme.md new file mode 100644 index 000000000..d7ea5bcd9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/readme.md @@ -0,0 +1,562 @@ +# Virtual Machines `[Microsoft.Compute/virtualMachines]` + +This module deploys one Virtual Machine with one or multiple nics and optionally one or multiple public IPs. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Automanage/configurationProfileAssignments` | 2021-04-30-preview | +| `Microsoft.Compute/virtualMachines` | 2021-07-01 | +| `Microsoft.Compute/virtualMachines/extensions` | 2021-07-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/networkInterfaces` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `adminUsername` | secureString | | Administrator username | +| `imageReference` | object | | OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `nicConfigurations` | array | | Configures NICs and PIPs. | +| `osDisk` | object | | Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `osType` | string | `[Windows, Linux]` | The chosen OS type | +| `vmSize` | string | | Specifies the size for the VMs | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | `''` | | When specifying a Windows Virtual Machine, this value should be passed | +| `allowExtensionOperations` | bool | `True` | | Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine. | +| `availabilitySetName` | string | `''` | | Resource name of an availability set. Cannot be used in combination with availability zone nor scale set. | +| `availabilityZone` | int | `0` | `[0, 1, 2, 3]` | If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set. | +| `backupPolicyName` | string | `'DefaultPolicy'` | | Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. | +| `backupVaultName` | string | `''` | | Recovery service vault name to add VMs to backup. | +| `backupVaultResourceGroup` | string | `[resourceGroup().name]` | | Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. | +| `bootDiagnosticStorageAccountName` | string | `''` | | Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Storage account boot diagnostic base URI. | +| `certificatesToBeInstalled` | array | `[]` | | Specifies set of certificates that should be installed onto the virtual machine. | +| `configurationProfileAssignments` | array | `[]` | | Any VM configuration profile assignments | +| `customData` | string | `''` | | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `dedicatedHostId` | string | `''` | | Specifies resource ID about the dedicated host that the virtual machine resides in. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disablePasswordAuthentication` | bool | `False` | | Specifies whether password authentication should be disabled. | +| `enableAutomaticUpdates` | bool | `True` | | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableEvictionPolicy` | bool | `False` | | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | `False` | | Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `extensionAntiMalwareConfig` | object | `{object}` | | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptProtectedSetting` | secureObject | `{object}` | | Any object that contains the extension specific protected settings | +| `extensionDependencyAgentConfig` | object | `{object}` | | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | `''` | | Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `licenseType` | string | `''` | `[Windows_Client, Windows_Server, ]` | Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxPriceForLowPriorityVm` | string | `''` | | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `monitoringWorkspaceId` | string | `''` | | Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true. | +| `name` | string | `[take(toLower(uniqueString(resourceGroup().name)), 10)]` | | The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name. | +| `nicdiagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `nicDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the NIC diagnostic setting, if deployed. | +| `pipdiagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `pipdiagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `pipDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the PIP diagnostic setting, if deployed. | +| `plan` | object | `{object}` | | Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | `''` | | Resource name of a proximity placement group. | +| `publicKeys` | array | `[]` | | The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sasTokenValidityLength` | string | `'PT8H'` | | SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `secureBootEnabled` | bool | `False` | | Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `securityType` | string | `''` | | Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `''` | | Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | `False` | | The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vmComputerNamesTransformation` | string | `'none'` | | Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'. | +| `vmPriority` | string | `'Regular'` | `[Regular, Low, Spot]` | Specifies the priority for the virtual machine. | +| `vTpmEnabled` | bool | `False` | | Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +### Parameter Usage: `imageReference` + +#### Marketplace images + +```json +"imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } +} +``` + +#### Custom images + +```json +"imageReference": { + "value": { + "id": "/subscriptions/12345-6789-1011-1213-15161718/resourceGroups/rg-name/providers/Microsoft.Compute/images/imagename" + } +} +``` + +### Parameter Usage: `plan` + +```json +"plan": { + "value": { + "name": "qvsa-25", + "product": "qualys-virtual-scanner", + "publisher": "qualysguard" + } +} +``` + +### Parameter Usage: `osDisk` + +```json + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { // Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. + "id": "/subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/" + } + } + } +} +``` + +### Parameter Usage: `dataDisks` + +```json +"dataDisks": { + "value": [{ + "caching": "ReadOnly", + "createOption": "Empty", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }] +} +``` + +### Parameter Usage: `windowsConfiguration` + +To set the time zone of a VM with the timeZone parameter inside windowsConfiguration, use the following PS command to get the correct options: + +```powershell +Get-TimeZone -ListAvailable | Select ID +``` + +```json +"windowsConfiguration": { + "provisionVMAgent": "boolean", + "enableAutomaticUpdates": "boolean", + "timeZone": "string", + "additionalUnattendContent": [ + { + "passName": "OobeSystem", + "componentName": "Microsoft-Windows-Shell-Setup", + "settingName": "string", + "content": "string" + } + ], + "winRM": { + "listeners": [ + { + "protocol": "string", + "certificateUrl": "string" + } + ] + } +} +``` + +### Parameter Usage: `linuxConfiguration` + +```json +"linuxConfiguration": { + "disablePasswordAuthentication": "boolean", + "ssh": { + "publicKeys": [ + { + "path": "string", + "keyData": "string" + } + ] + }, + "provisionVMAgent": "boolean" + }, + "secrets": [ + { + "sourceVault": { + "id": "string" + }, + "vaultCertificates": [ + { + "certificateUrl": "string", + "certificateStore": "string" + } + ] + } + ], + "allowExtensionOperations": "boolean", + "requireGuestProvisionSignal": "boolean" +} +``` + +### Parameter Usage: `nicConfigurations` + +Comments: +- The field `nicSuffix` and `subnetId` are mandatory. +- If `enablePublicIP` is set to true, then `publicIpNameSuffix` is also mandatory. +- Each IP config needs to have the mandatory field `name`. +- If not disabled, `enableAcceleratedNetworking` is considered `true` by default and requires the VM to be deployed with a supported OS and VM size. + +```json +"nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "ipConfigurations": [ + { + "name": "ipconfig1", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "" + ] + } + ] + } + }, + { + "name": "ipconfig2", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + } + ], + "nsgId": "/subscriptions//resourceGroups//providers/Microsoft.Network/networkSecurityGroups/", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "" + ] + } + ] + }, + { + "nicSuffix": "-nic-02", + "ipConfigurations": [ + { + "name": "ipconfig1", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-02" + } + }, + { + "name": "ipconfig2", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "privateIPAllocationMethod": "Static", + "vmIPAddress": "10.0.0.9" + } + ] + } + ] +} +``` + +### Parameter Usage: `configurationProfileAssignments` + +```json +"configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest" + ] +} +``` + +### Parameter Usage: `extensionDomainJoinConfig` + +```json +"extensionDomainJoinConfig": { + "value": { + "enabled": true, + "settings": { + "domainName": "contoso.com", + "domainJoinUser": "test.user@testcompany.com", + "domainJoinOU": "OU=testOU; DC=contoso; DC=com", + "domainJoinRestart": true, + "domainJoinOptions": 3 + } + } +}, +"extensionDomainJoinPassword": { + "keyVault": { + "id": "/subscriptions/62826c76-d304-46d8-a0f6-718dbdcc536c/resourceGroups/WVD-Mgmt-TO-RG/providers/Microsoft.KeyVault/vaults/wvd-to-kvlt" + }, + "secretName": "domainJoinUser02-Password" +} +``` + +### Parameter Usage: `extensionAntiMalwareConfig` + +Only for OSType Windows + +```json +"extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } +} +``` + +### Parameter Usage: `extensionDiskEncryptionConfig` + +```json +"extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://mykeyvault.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionKeyURL": "https://mykeyvault.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", //'RSA-OAEP'/'RSA-OAEP-256'/'RSA1_5' + "VolumeType": "All", //'OS'/'Data'/'All' + "ResizeOSDisk": "false" + } + } +} +``` + +### Parameter Usage: `extensionDSCConfig` + +```json +"extensionDSCConfig": { + "value": { + { + "enabled": true, + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "http://validURLToConfigLocation", + "script": "ConfigurationScript.ps1", + "function": "ConfigurationFunction" + }, + "configurationArguments": { + "argument1": "Value1", + "argument2": "Value2" + }, + "configurationData": { + "url": "https://foo.psd1" + }, + "privacy": { + "dataCollection": "enable" + }, + "advancedOptions": { + "forcePullAndApply": false, + "downloadMappings": { + "specificDependencyKey": "https://myCustomDependencyLocation" + } + } + }, + "protectedSettings": { + "configurationArguments": { + "mySecret": "MyPlaceholder" + }, + "configurationUrlSasToken": "MyPlaceholder", + "configurationDataUrlSasToken": "MyPlaceholder" + } + } + } +} +``` + +### Parameter Usage: `extensionCustomScriptConfig` + +```json +"extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + //storage account with public container (no SAS token is required) OR other public URL (not a storage account) + { + "uri": "https://github.com/myProject/File3.ps1", + "storageAccountId": "" + } + ], + "settings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File testscript.ps1" + } + } +} +``` + +### Parameter Usage: `extensionCustomScriptProtectedSetting` + +This is used if you are going to use secrets or other sensitive information that you don't want to be visible in the deployment and logs. + +```json +"extensionCustomScriptProtectedSetting": { + "value": [ + "commandToExecute": "mycommandToRun -someParam MYSECRET" + ] +} +``` +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VM. | +| `resourceGroupName` | string | The name of the resource group the VM was created in. | +| `resourceId` | string | The resource ID of the VM. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Define resources with Bicep and ARM templates](https://docs.microsoft.com/en-us/azure/templates) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networkinterfaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkInterfaces) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Backupfabrics/Protectioncontainers/Protecteditems](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-06-01/vaults/backupFabrics/protectionContainers/protectedItems) +- [Virtualmachines](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines) +- [Virtualmachines/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) diff --git a/carml/1.0.1/Microsoft.Compute/virtualMachines/version.json b/carml/1.0.1/Microsoft.Compute/virtualMachines/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Compute/virtualMachines/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/carml/1.0.1/Microsoft.Consumption/budgets/.parameters/parameters.json b/carml/1.0.1/Microsoft.Consumption/budgets/.parameters/parameters.json new file mode 100644 index 000000000..4ab50cd80 --- /dev/null +++ b/carml/1.0.1/Microsoft.Consumption/budgets/.parameters/parameters.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "amount": { + "value": 500 + }, + "thresholds": { + "value": [ + 50, + 75, + 90, + 100, + 110 + ] + }, + "contactEmails": { + "value": [ + "dummy@contoso.com" + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Consumption/budgets/deploy.bicep b/carml/1.0.1/Microsoft.Consumption/budgets/deploy.bicep new file mode 100644 index 000000000..83d1b40ed --- /dev/null +++ b/carml/1.0.1/Microsoft.Consumption/budgets/deploy.bicep @@ -0,0 +1,108 @@ +targetScope = 'subscription' + +@description('Optional. The name of the budget.') +param name string = '' + +@allowed([ + 'Cost' + 'Usage' +]) +@description('Optional. The category of the budget, whether the budget tracks cost or usage.') +param category string = 'Cost' + +@description('Required. The total amount of cost or usage to track with the budget.') +param amount int + +@allowed([ + 'Monthly' + 'Quarterly' + 'Annually' + 'BillingMonth' + 'BillingQuarter' + 'BillingAnnual' +]) +@description('Optional. The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers.') +param resetPeriod string = 'Monthly' + +@description('Required. The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month).') +param startDate string = '${utcNow('yyyy')}-${utcNow('MM')}-01T00:00:00Z' + +@description('Optional. The end date for the budget. If not provided, it will default to 10 years from the start date.') +param endDate string = '' + +@maxLength(5) +@description('Optional. Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000.') +param thresholds array = [ + 50 + 75 + 90 + 100 + 110 +] + +@description('Optional. The list of email addresses to send the budget notification to when the thresholds are exceeded.') +param contactEmails array = [] + +@description('Optional. The list of contact roles to send the budget notification to when the thresholds are exceeded.') +param contactRoles array = [] + +@description('Optional. List of action group resource IDs that will receive the alert.') +param actionGroups array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +var budgetNameVar = empty(name) ? '${resetPeriod}-${category}-Budget' : name +var notificationsArray = [for threshold in thresholds: { + 'Actual_GreaterThan_${threshold}_Percentage': { + enabled: true + operator: 'GreaterThan' + threshold: threshold + contactEmails: empty(contactEmails) ? null : array(contactEmails) + contactRoles: empty(contactRoles) ? null : array(contactRoles) + contactGroups: empty(actionGroups) ? null : array(actionGroups) + thresholdType: 'Actual' + } +}] + +var notifications = json(replace(replace(replace(string(notificationsArray), '[{', '{'), '}]', '}'), '}},{', '},')) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource budget 'Microsoft.Consumption/budgets@2019-05-01' = { + name: budgetNameVar + properties: { + category: category + amount: amount + timeGrain: resetPeriod + timePeriod: { + startDate: startDate + endDate: endDate + } + filter: {} + notifications: notifications + } +} + +@description('The name of the budget') +output name string = budget.name + +@description('The resource ID of the budget') +output resourceId string = budget.id + +@description('The subscription the budget was deployed into') +output subscriptionName string = subscription().displayName diff --git a/carml/1.0.1/Microsoft.Consumption/budgets/readme.md b/carml/1.0.1/Microsoft.Consumption/budgets/readme.md new file mode 100644 index 000000000..ea6813de4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Consumption/budgets/readme.md @@ -0,0 +1,51 @@ +# Budgets `[Microsoft.Consumption/budgets]` + +This module deploys budgets for subscriptions. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Consumption/budgets` | 2019-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `amount` | int | | The total amount of cost or usage to track with the budget. | +| `startDate` | string | `[format('{0}-{1}-01T00:00:00Z', utcNow('yyyy'), utcNow('MM'))]` | The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month). | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actionGroups` | array | `[]` | | List of action group resource IDs that will receive the alert. | +| `category` | string | `'Cost'` | `[Cost, Usage]` | The category of the budget, whether the budget tracks cost or usage. | +| `contactEmails` | array | `[]` | | The list of email addresses to send the budget notification to when the thresholds are exceeded. | +| `contactRoles` | array | `[]` | | The list of contact roles to send the budget notification to when the thresholds are exceeded. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endDate` | string | `''` | | The end date for the budget. If not provided, it will default to 10 years from the start date. | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `name` | string | `''` | | The name of the budget. | +| `resetPeriod` | string | `'Monthly'` | `[Monthly, Quarterly, Annually, BillingMonth, BillingQuarter, BillingAnnual]` | The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers. | +| `thresholds` | array | `[50, 75, 90, 100, 110]` | | Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the budget | +| `resourceId` | string | The resource ID of the budget | +| `subscriptionName` | string | The subscription the budget was deployed into | + +## Template references + +- [Budgets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Consumption/2019-05-01/budgets) diff --git a/carml/1.0.1/Microsoft.Consumption/budgets/version.json b/carml/1.0.1/Microsoft.Consumption/budgets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Consumption/budgets/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/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/.parameters/parameters.json new file mode 100644 index 000000000..1fdcb27db --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/.parameters/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": "<>-az-acg-x-001" + }, + "containerName": { + "value": "<>-az-aci-x-001" + }, + "image": { + "value": "mcr.microsoft.com/azuredocs/aci-helloworld" + }, + "ports": { + "value": [ + { + "protocol": "Tcp", + "port": "80" + }, + { + "protocol": "Tcp", + "port": "443" + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/deploy.bicep b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/deploy.bicep new file mode 100644 index 000000000..2948d859b --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/deploy.bicep @@ -0,0 +1,136 @@ +@description('Required. Name for the container group.') +param name string + +@description('Required. Name for the container.') +param containername string + +@description('Required. Name of the image.') +param image string + +@description('Optional. Port to open on the container and the public IP address.') +param ports array = [ + { + name: 'Tcp' + value: '443' + } +] + +@description('Optional. The number of CPU cores to allocate to the container.') +param cpuCores int = 2 + +@description('Optional. The amount of memory to allocate to the container in gigabytes.') +param memoryInGB int = 2 + +@description('Optional. The operating system type required by the containers in the container group. - Windows or Linux.') +param osType string = 'Linux' + +@description('Optional. Restart policy for all containers within the container group. - Always: Always restart. OnFailure: Restart on failure. Never: Never restart. - Always, OnFailure, Never') +param restartPolicy string = 'Always' + +@description('Optional. Specifies if the IP is exposed to the public internet or private VNET. - Public or Private') +param ipAddressType string = 'Public' + +@description('Optional. The image registry credentials by which the container group is created from.') +param imageRegistryCredentials array = [] + +@description('Optional. Envrionment variables of the container group.') +param environmentVariables array = [] + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource containergroup 'Microsoft.ContainerInstance/containerGroups@2021-03-01' = { + name: name + location: location + identity: identity + tags: tags + properties: { + containers: [ + { + name: containername + properties: { + command: [] + image: image + ports: ports + resources: { + requests: { + cpu: cpuCores + memoryInGB: memoryInGB + } + } + environmentVariables: environmentVariables + } + } + ] + imageRegistryCredentials: imageRegistryCredentials + restartPolicy: restartPolicy + osType: osType + ipAddress: { + type: ipAddressType + ports: ports + } + } +} + +resource containergroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${containergroup.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: containergroup +} + +@description('The name of the container group') +output name string = containergroup.name + +@description('The resource ID of the container group') +output resourceId string = containergroup.id + +@description('The resource group the container group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The IPv4 address of the container group') +output iPv4Address string = containergroup.properties.ipAddress.ip + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(containergroup.identity, 'principalId') ? containergroup.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/readme.md b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/readme.md new file mode 100644 index 000000000..454547241 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/readme.md @@ -0,0 +1,107 @@ +# Container Instances `[Microsoft.ContainerInstance/containerGroups]` + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +### Container groups in Azure Container Instances + +The top-level resource in Azure Container Instances is the container group. A container group is a collection of containers that get scheduled on the same host machine. The containers in a container group share a lifecycle, resources, local network, and storage volumes. It's similar in concept to a pod in Kubernetes. + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.ContainerInstance/containerGroups` | 2021-03-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `containername` | string | Name for the container. | +| `image` | string | Name of the image. | +| `name` | string | Name for the container group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cpuCores` | int | `2` | | The number of CPU cores to allocate to the container. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `environmentVariables` | array | `[]` | | Envrionment variables of the container group. | +| `imageRegistryCredentials` | array | `[]` | | The image registry credentials by which the container group is created from. | +| `ipAddressType` | string | `'Public'` | | Specifies if the IP is exposed to the public internet or private VNET. - Public or Private | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `memoryInGB` | int | `2` | | The amount of memory to allocate to the container in gigabytes. | +| `osType` | string | `'Linux'` | | The operating system type required by the containers in the container group. - Windows or Linux. | +| `ports` | array | `[System.Collections.Hashtable]` | | Port to open on the container and the public IP address. | +| `restartPolicy` | string | `'Always'` | | Restart policy for all containers within the container group. - Always: Always restart. OnFailure: Restart on failure. Never: Never restart. - Always, OnFailure, Never | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `imageRegistryCredentials` + +The image registry credentials by which the container group is created from. + +```json + "imageRegistryCredentials": { + "value": [ + { + "server": "sxxazacrx001.azurecr.io", + "username": "sxxazacrx001" + } + ] + } +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `iPv4Address` | string | The IPv4 address of the container group | +| `name` | string | The name of the container group | +| `resourceGroupName` | string | The resource group the container group was deployed into | +| `resourceId` | string | The resource ID of the container group | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Containergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerInstance/2021-03-01/containerGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/version.json b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerInstance/containerGroups/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/carml/1.0.1/Microsoft.ContainerRegistry/registries/.bicep/nested_privateEndpoints.bicep b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.bicep/nested_privateEndpoints.bicep new file mode 100644 index 000000000..9deaf8c02 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.bicep/nested_privateEndpoints.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? privateEndpointObj.privateDnsZoneResourceIds : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateEndpoint_privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..f7dcf7935 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'AcrDelete': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11') + 'AcrImageSigner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'AcrPush': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec') + 'AcrQuarantineReader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04') + 'AcrQuarantineWriter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource registry 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(registry.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: registry +}] diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.parameters/min.parameters.json new file mode 100644 index 000000000..255a9ddfc --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azacrmin001" + } + } +} diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/.parameters/parameters.json b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.parameters/parameters.json new file mode 100644 index 000000000..c900c68be --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/.parameters/parameters.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azacrx001" + }, + "acrAdminUserEnabled": { + "value": false + }, + "acrSku": { + "value": "Premium" + }, + "exportPolicyStatus": { + "value": "enabled" + }, + "quarantinePolicyStatus": { + "value": "enabled" + }, + "trustPolicyStatus": { + "value": "enabled" + }, + "replications": { + "value": [ + { + "name": "northeurope", + "location": "northeurope" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "registry" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/deploy.bicep b/carml/1.0.1/Microsoft.ContainerRegistry/registries/deploy.bicep new file mode 100644 index 000000000..870fa0931 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/deploy.bicep @@ -0,0 +1,305 @@ +@description('Required. Name of your Azure container registry') +@minLength(5) +@maxLength(50) +param name string + +@description('Optional. Enable admin user that have push / pull permission to the registry.') +param acrAdminUserEnabled bool = false + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tier of your Azure container registry.') +@allowed([ + 'Basic' + 'Premium' + 'Standard' +]) +param acrSku string = 'Basic' + +@allowed([ + 'disabled' + 'enabled' +]) +@description('Optional. The value that indicates whether the export policy is enabled or not.') +param exportPolicyStatus string = 'disabled' + +@allowed([ + 'disabled' + 'enabled' +]) +@description('Optional. The value that indicates whether the quarantine policy is enabled or not.') +param quarantinePolicyStatus string = 'disabled' + +@allowed([ + 'disabled' + 'enabled' +]) +@description('Optional. The value that indicates whether the trust policy is enabled or not.') +param trustPolicyStatus string = 'disabled' + +@allowed([ + 'disabled' + 'enabled' +]) +@description('Optional. The value that indicates whether the retention policy is enabled or not.') +param retentionPolicyStatus string = 'enabled' + +@description('Optional. The number of days to retain an untagged manifest after which it gets purged.') +param retentionPolicyDays int = 15 + +@allowed([ + 'disabled' + 'enabled' +]) +@description('Optional. The value that indicates whether encryption is enabled or not.') +param encryptionStatus string = 'disabled' + +@description('Optional. Identity which will be used to access key vault and Key vault uri to access the encryption key.') +param keyVaultProperties object = {} + +@description('Optional. Enable a single data endpoint per region for serving data. Not relevant in case of disabled public access.') +param dataEndpointEnabled bool = false + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Whether or not public network access is allowed for the container registry. - Enabled or Disabled') +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Whether to allow trusted Azure services to access a network restricted registry. Not relevant in case of public access. - AzureServices or None') +param networkRuleBypassOptions string = 'AzureServices' + +@allowed([ + 'Allow' + 'Deny' +]) +@description('Optional. The default action of allow or deny when no other rules match.') +param networkRuleSetDefaultAction string = 'Deny' + +@description('Optional. The IP ACL rules.') +param networkRuleSetIpRules array = [] + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Whether or not zone redundancy is enabled for this container registry') +param zoneRedundancy string = 'Disabled' + +@description('Optional. All replications to create') +param replications array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ContainerRegistryRepositoryEvents' + 'ContainerRegistryLoginEvents' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ContainerRegistryRepositoryEvents' + 'ContainerRegistryLoginEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource registry 'Microsoft.ContainerRegistry/registries@2021-09-01' = { + name: name + location: location + identity: identity + tags: tags + sku: { + name: acrSku + } + properties: { + adminUserEnabled: acrAdminUserEnabled + encryption: acrSku == 'Premium' ? { + keyVaultProperties: !empty(keyVaultProperties) ? keyVaultProperties : null + status: encryptionStatus + } : null + policies: { + exportPolicy: acrSku == 'Premium' ? { + status: exportPolicyStatus + } : null + quarantinePolicy: { + status: quarantinePolicyStatus + } + trustPolicy: { + type: 'Notary' + status: trustPolicyStatus + } + retentionPolicy: acrSku == 'Premium' ? { + days: retentionPolicyDays + status: retentionPolicyStatus + } : null + } + dataEndpointEnabled: dataEndpointEnabled + publicNetworkAccess: publicNetworkAccess + networkRuleBypassOptions: networkRuleBypassOptions + networkRuleSet: !empty(networkRuleSetIpRules) ? { + defaultAction: networkRuleSetDefaultAction + ipRules: networkRuleSetIpRules + } : null + zoneRedundancy: acrSku == 'Premium' ? zoneRedundancy : null + } +} + +module registry_replications 'replications/deploy.bicep' = [for (replication, index) in replications: { + name: '${uniqueString(deployment().name, location)}-Registry-Replication-${index}' + params: { + name: replication.name + registryName: registry.name + location: replication.location + regionEndpointEnabled: contains(replication, 'regionEndpointEnabled') ? replication.regionEndpointEnabled : true + zoneRedundancy: contains(replication, 'zoneRedundancy') ? replication.zoneRedundancy : 'Disabled' + tags: contains(replication, 'tags') ? replication.tags : {} + } +}] + +resource registry_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${registry.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: registry +} + +resource registry_diagnosticSettingName 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: registry +} + +module registry_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ContainerRegistry-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: registry.id + } +}] + +module registry_privateEndpoints '.bicep/nested_privateEndpoints.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-ContainerRegistry-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: registry.id + privateEndpointVnetLocation: empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The Name of the Azure container registry.') +output name string = registry.name + +@description('The reference to the Azure container registry.') +output loginServer string = reference(registry.id, '2019-05-01').loginServer + +@description('The name of the Azure container registry.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Azure container registry.') +output resourceId string = registry.id + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(registry.identity, 'principalId') ? registry.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/readme.md b/carml/1.0.1/Microsoft.ContainerRegistry/registries/readme.md new file mode 100644 index 000000000..a8b42d152 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/readme.md @@ -0,0 +1,204 @@ +# Container Registries `[Microsoft.ContainerRegistry/registries]` + +Azure Container Registry is a managed, private Docker registry service based on the open-source Docker Registry 2.0. Create and maintain Azure container registries to store and manage your private Docker container images and related artifacts. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ContainerRegistry/registries` | 2021-09-01 | +| `Microsoft.ContainerRegistry/registries/replications` | 2021-12-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of your Azure container registry | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `acrAdminUserEnabled` | bool | `False` | | Enable admin user that have push / pull permission to the registry. | +| `acrSku` | string | `'Basic'` | `[Basic, Premium, Standard]` | Tier of your Azure container registry. | +| `dataEndpointEnabled` | bool | `False` | | Enable a single data endpoint per region for serving data. Not relevant in case of disabled public access. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ContainerRegistryRepositoryEvents, ContainerRegistryLoginEvents]` | `[ContainerRegistryRepositoryEvents, ContainerRegistryLoginEvents]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `encryptionStatus` | string | `'disabled'` | `[disabled, enabled]` | The value that indicates whether encryption is enabled or not. | +| `exportPolicyStatus` | string | `'disabled'` | `[disabled, enabled]` | The value that indicates whether the export policy is enabled or not. | +| `keyVaultProperties` | object | `{object}` | | Identity which will be used to access key vault and Key vault uri to access the encryption key. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `networkRuleBypassOptions` | string | `'AzureServices'` | | Whether to allow trusted Azure services to access a network restricted registry. Not relevant in case of public access. - AzureServices or None | +| `networkRuleSetDefaultAction` | string | `'Deny'` | `[Allow, Deny]` | The default action of allow or deny when no other rules match. | +| `networkRuleSetIpRules` | array | `[]` | | The IP ACL rules. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `publicNetworkAccess` | string | `'Enabled'` | `[Disabled, Enabled]` | Whether or not public network access is allowed for the container registry. - Enabled or Disabled | +| `quarantinePolicyStatus` | string | `'disabled'` | `[disabled, enabled]` | The value that indicates whether the quarantine policy is enabled or not. | +| `replications` | _[replications](replications/readme.md)_ array | `[]` | | All replications to create | +| `retentionPolicyDays` | int | `15` | | The number of days to retain an untagged manifest after which it gets purged. | +| `retentionPolicyStatus` | string | `'enabled'` | `[disabled, enabled]` | The value that indicates whether the retention policy is enabled or not. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `trustPolicyStatus` | string | `'disabled'` | `[disabled, enabled]` | The value that indicates whether the trust policy is enabled or not. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `zoneRedundancy` | string | `'Disabled'` | `[Disabled, Enabled]` | Whether or not zone redundancy is enabled for this container registry | + + +### Parameter Usage: `keyVaultProperties` + +```json +"keyVaultProperties": { + "value": { + "identity": "string", // The client id of the identity which will be used to access key vault. + "keyIdentifier": "string" // Key vault uri to access the encryption key. + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `imageRegistryCredentials` + +The image registry credentials by which the container group is created from. + +```json + "acrName": { + "value": { + "server": "acrx001", + } + }, + "acrAdminUserEnabled": { + "value": false + } +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `loginServer` | string | The reference to the Azure container registry. | +| `name` | string | The Name of the Azure container registry. | +| `resourceGroupName` | string | The name of the Azure container registry. | +| `resourceId` | string | The resource ID of the Azure container registry. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Registries](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerRegistry/2021-09-01/registries) +- [Registries/Replications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerRegistry/2021-12-01-preview/registries/replications) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/deploy.bicep b/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/deploy.bicep new file mode 100644 index 000000000..341b6e44b --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/deploy.bicep @@ -0,0 +1,60 @@ +@description('Required. The name of the registry.') +param registryName string + +@description('Required. The name of the replication.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Specifies whether the replication regional endpoint is enabled. Requests will not be routed to a replication whose regional endpoint is disabled, however its data will continue to be synced with other replications.') +param regionEndpointEnabled bool = true + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Whether or not zone redundancy is enabled for this container registry') +param zoneRedundancy string = 'Disabled' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource registry 'Microsoft.ContainerRegistry/registries@2021-09-01' existing = { + name: registryName +} + +resource replication 'Microsoft.ContainerRegistry/registries/replications@2021-12-01-preview' = { + name: name + parent: registry + location: location + tags: tags + properties: { + regionEndpointEnabled: regionEndpointEnabled + zoneRedundancy: zoneRedundancy + } +} + +@description('The name of the replication.') +output name string = replication.name + +@description('The resource ID of the replication.') +output resourceId string = replication.id + +@description('The name of the resource group the replication was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/readme.md b/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/readme.md new file mode 100644 index 000000000..f74780fcd --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/readme.md @@ -0,0 +1,63 @@ +# ContainerRegistry Registries Replications `[Microsoft.ContainerRegistry/registries/replications]` + +This module deploys ContainerRegistry Registries Replications. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ContainerRegistry/registries/replications` | 2021-12-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication. | +| `registryName` | string | The name of the registry. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `regionEndpointEnabled` | bool | `True` | | Specifies whether the replication regional endpoint is enabled. Requests will not be routed to a replication whose regional endpoint is disabled, however its data will continue to be synced with other replications. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `zoneRedundancy` | string | `'Disabled'` | `[Disabled, Enabled]` | Whether or not zone redundancy is enabled for this container registry | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication. | +| `resourceGroupName` | string | The name of the resource group the replication was created in. | +| `resourceId` | string | The resource ID of the replication. | + +## Template references + +- [Registries/Replications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerRegistry/2021-12-01-preview/registries/replications) diff --git a/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/version.json b/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/replications/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/carml/1.0.1/Microsoft.ContainerRegistry/registries/version.json b/carml/1.0.1/Microsoft.ContainerRegistry/registries/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerRegistry/registries/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/carml/1.0.1/Microsoft.ContainerService/managedClusters/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ContainerService/managedClusters/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..97a7c2418 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8') + 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f') + 'Azure Kubernetes Service Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8') + 'Azure Kubernetes Service RBAC Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3498e952-d568-435e-9b2c-8d77e338d7f7') + 'Azure Kubernetes Service RBAC Cluster Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b') + 'Azure Kubernetes Service RBAC Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f6c6a51-bcf8-42ba-9220-52d62157d7db') + 'Azure Kubernetes Service RBAC Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2021-07-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(managedCluster.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: managedCluster +}] diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/.parameters/azure.parameters.json b/carml/1.0.1/Microsoft.ContainerService/managedClusters/.parameters/azure.parameters.json new file mode 100644 index 000000000..10a7e7af1 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/.parameters/azure.parameters.json @@ -0,0 +1,117 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-aks-azure-001" + }, + "primaryAgentPoolProfile": { + "value": [ + { + "name": "systempool", + "osDiskSizeGB": 0, + "count": 1, + "enableAutoScaling": true, + "minCount": 1, + "maxCount": 3, + "vmSize": "Standard_DS2_v2", + "osType": "Linux", + "storageProfile": "ManagedDisks", + "type": "VirtualMachineScaleSets", + "mode": "System", + "vnetSubnetID": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-aks/subnets/Primary", + "serviceCidr": "", + "maxPods": 30, + "availabilityZones": [ + "1" + ] + } + ] + }, + "aksClusterNetworkPlugin": { + "value": "azure" + }, + "agentPools": { + "value": [ + { + "name": "userpool1", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User", + "vnetSubnetID": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-aks/subnets/Secondary" + }, + { + "name": "userpool2", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User", + "vnetSubnetID": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-aks/subnets/Tertiary" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/.parameters/kubenet.parameters.json b/carml/1.0.1/Microsoft.ContainerService/managedClusters/.parameters/kubenet.parameters.json new file mode 100644 index 000000000..3e274f46c --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/.parameters/kubenet.parameters.json @@ -0,0 +1,116 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-aks-kubenet-001" + }, + "primaryAgentPoolProfile": { + "value": [ + { + "name": "systempool", + "osDiskSizeGB": 0, + "count": 1, + "enableAutoScaling": true, + "minCount": 1, + "maxCount": 3, + "vmSize": "Standard_DS2_v2", + "osType": "Linux", + "storageProfile": "ManagedDisks", + "type": "VirtualMachineScaleSets", + "mode": "System", + "serviceCidr": "", + "maxPods": 30, + "availabilityZones": [ + "1" + ] + } + ] + }, + "aksClusterNetworkPlugin": { + "value": "kubenet" + }, + "agentPools": { + "value": [ + { + "name": "userpool1", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User" + }, + { + "name": "userpool2", + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 3, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1" + ], + "minPods": 2, + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "User" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/deploy.bicep b/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/deploy.bicep new file mode 100644 index 000000000..b57a756c9 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/deploy.bicep @@ -0,0 +1,242 @@ +@description('Required. Name of the managed cluster') +@minLength(1) +param managedClusterName string + +@description('Required. Name of the agent pool') +param name string + +@description('Optional. The list of Availability zones to use for nodes. This can only be specified if the AgentPoolType property is "VirtualMachineScaleSets". ') +param availabilityZones array = [] + +@description('Optional. Desired Number of agents (VMs) specified to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1.') +@minValue(0) +@maxValue(1000) +param count int = 1 + +@description('Optional. This is the ARM ID of the source object to be used to create the target object.') +param sourceResourceId string = '' + +@description('Optional. Whether to enable auto-scaler') +@allowed([ + true + false +]) +param enableAutoScaling bool = false + +@description('Optional. This is only supported on certain VM sizes and in certain Azure regions. For more information, see: /azure/aks/enable-host-encryption ') +@allowed([ + true + false +]) +param enableEncryptionAtHost bool = false + +@description('Optional. See Add a FIPS-enabled node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool-preview) for more details.') +@allowed([ + true + false +]) +param enableFIPS bool = false + +@description('Optional. Some scenarios may require nodes in a node pool to receive their own dedicated public IP addresses. A common scenario is for gaming workloads, where a console needs to make a direct connection to a cloud virtual machine to minimize hops. For more information see assigning a public IP per node (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools). The default is false.') +@allowed([ + true + false +]) +param enableNodePublicIP bool = false + +@description('Optional. Whether to enable UltraSSD') +@allowed([ + true + false +]) +param enableUltraSSD bool = false + +@description('Optional. GPUInstanceProfile to be used to specify GPU MIG instance profile for supported GPU VM SKU.') +@allowed([ + 'MIG1g' + 'MIG2g' + 'MIG3g' + 'MIG4g' + 'MIG7g' + '' +]) +param gpuInstanceProfile string = '' + +@description('Optional. Determines the placement of emptyDir volumes, container runtime data root, and Kubelet ephemeral storage.') +param kubeletDiskType string = '' + +@description('Optional. The maximum number of nodes for auto-scaling') +param maxCount int = -1 + +@description('Optional. The maximum number of pods that can run on a node.') +param maxPods int = -1 + +@description('Optional. The minimum number of nodes for auto-scaling') +param minCount int = -1 + +@description('Optional. A cluster must have at least one "System" Agent Pool at all times. For additional information on agent pool restrictions and best practices, see: /azure/aks/use-system-pools') +param mode string = '' + +@description('Optional. The node labels to be persisted across all nodes in agent pool.') +param nodeLabels object = {} + +@description('Optional. ResourceId of the node PublicIPPrefix') +param nodePublicIpPrefixId string = '' + +@description('Optional. The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. ') +param nodeTaints array = [] + +@description('Optional. As a best practice, you should upgrade all node pools in an AKS cluster to the same Kubernetes version. The node pool version must have the same major version as the control plane. The node pool minor version must be within two minor versions of the control plane version. The node pool version cannot be greater than the control plane version. For more information see upgrading a node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#upgrade-a-node-pool).') +param orchestratorVersion string = '' + +@description('Optional. OS Disk Size in GB to be used to specify the disk size for every machine in the master/agent pool. If you specify 0, it will apply the default osDisk size according to the vmSize specified.') +param osDiskSizeGB int = 0 + +@description('Optional. The default is "Ephemeral" if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, defaults to "Managed". May not be changed after creation. For more information see Ephemeral OS (https://docs.microsoft.com/en-us/azure/aks/cluster-configuration#ephemeral-os).') +@allowed([ + 'Ephemeral' + 'Managed' + '' +]) +param osDiskType string = '' + +@description('Optional. Specifies an OS SKU. This value must not be specified if OSType is Windows.') +@allowed([ + 'CBLMariner' + 'Ubuntu' + '' +]) +param osSku string = '' + +@description('Optional. The operating system type. The default is Linux.') +@allowed([ + 'Linux' + 'Windows' +]) +param osType string = 'Linux' + +@description('Optional. Subnet ID for the pod IPs. If omitted, pod IPs are statically assigned on the node subnet (see vnetSubnetID for more details). This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} ') +param podSubnetId string = '' + +@description('Optional. The ID for the Proximity Placement Group.') +param proximityPlacementGroupId string = '' + +@description('Optional. Describes how VMs are added to or removed from Agent Pools. See billing states (https://docs.microsoft.com/en-us/azure/virtual-machines/states-billing).') +@allowed([ + 'Deallocate' + 'Delete' +]) +param scaleDownMode string = 'Delete' + +@description('Optional. The eviction policy specifies what to do with the VM when it is evicted. The default is Delete. For more information about eviction see spot VMs ') +@allowed([ + 'Deallocate' + 'Delete' +]) +param scaleSetEvictionPolicy string = 'Delete' + +@description('Optional. The Virtual Machine Scale Set priority.') +@allowed([ + 'Regular' + 'Spot' + '' +]) +param scaleSetPriority string = '' + +@description('Optional. Possible values are any decimal value greater than zero or -1 which indicates the willingness to pay any on-demand price. For more details on spot pricing, see spot VMs pricing (https://docs.microsoft.com/en-us/azure/virtual-machines/spot-vms#pricing)') +param spotMaxPrice int = -1 + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The type of Agent Pool.') +param type string = '' + +@description('Optional. This can either be set to an integer (e.g. "5") or a percentage (e.g. "50%"). If a percentage is specified, it is the percentage of the total agent pool size at the time of the upgrade. For percentages, fractional nodes are rounded up. If not specified, the default is 1. For more information, including best practices, see: /azure/aks/upgrade-cluster#customize-node-surge-upgrade') +param maxSurge string = '' + +@description('Optional. VM size. VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: /azure/aks/quotas-skus-regions') +param vmSize string = 'Standard_D2s_v3' + +@description('Optional. Node Subnet ID. If this is not specified, a VNET and subnet will be generated and used. If no podSubnetID is specified, this applies to nodes and pods, otherwise it applies to just nodes. This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} ') +param vnetSubnetId string = '' + +@description('Optional. Determines the type of workload a node can run.') +param workloadRuntime string = '' + +var creationData = { + sourceResourceId: !empty(sourceResourceId) ? sourceResourceId : null +} + +var upgradeSettings = { + maxSurge: maxSurge +} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2021-08-01' existing = { + name: managedClusterName +} + +resource agentPool 'Microsoft.ContainerService/managedClusters/agentPools@2021-08-01' = { + name: name + parent: managedCluster + properties: { + availabilityZones: availabilityZones + count: count + creationData: !empty(sourceResourceId) ? creationData : null + enableAutoScaling: enableAutoScaling + enableEncryptionAtHost: enableEncryptionAtHost + enableFIPS: enableFIPS + enableNodePublicIP: enableNodePublicIP + enableUltraSSD: enableUltraSSD + gpuInstanceProfile: !empty(gpuInstanceProfile) ? gpuInstanceProfile : null + kubeletDiskType: kubeletDiskType + maxCount: maxCount != -1 ? maxCount : null + maxPods: maxPods != -1 ? maxPods : null + minCount: minCount != -1 ? minCount : null + mode: !empty(mode) ? mode : null + nodeLabels: nodeLabels + nodePublicIPPrefixID: !empty(nodePublicIpPrefixId) ? nodePublicIpPrefixId : null + nodeTaints: nodeTaints + orchestratorVersion: orchestratorVersion + osDiskSizeGB: osDiskSizeGB != -1 ? osDiskSizeGB : null + osDiskType: !empty(osDiskType) ? osDiskType : null + osSKU: !empty(osSku) ? osSku : null + osType: osType + podSubnetID: !empty(podSubnetId) ? podSubnetId : null + proximityPlacementGroupID: !empty(proximityPlacementGroupId) ? proximityPlacementGroupId : null + scaleDownMode: scaleDownMode + scaleSetEvictionPolicy: scaleSetEvictionPolicy + scaleSetPriority: !empty(scaleSetPriority) ? scaleSetPriority : null + spotMaxPrice: spotMaxPrice + tags: tags + type: type + upgradeSettings: upgradeSettings + vmSize: vmSize + vnetSubnetID: vnetSubnetId + workloadRuntime: workloadRuntime + } +} + +@description('The name of the agent pool') +output name string = agentPool.name + +@description('The resource ID of the agent pool') +output resourceId string = agentPool.id + +@description('The resource group the agent pool was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/readme.md b/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/readme.md new file mode 100644 index 000000000..26a0daf33 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/readme.md @@ -0,0 +1,93 @@ +# Managed Cluster AgentPool `[Microsoft.ContainerService/managedClusters/agentPools]` + +This module deploys an Agent Pool for a Container Service Managed Cluster + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ContainerService/managedClusters/agentPools` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `managedClusterName` | string | Name of the managed cluster | +| `name` | string | Name of the agent pool | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `availabilityZones` | array | `[]` | | The list of Availability zones to use for nodes. This can only be specified if the AgentPoolType property is "VirtualMachineScaleSets". | +| `count` | int | `1` | | Desired Number of agents (VMs) specified to host docker containers. Allowed values must be in the range of 0 to 1000 (inclusive) for user pools and in the range of 1 to 1000 (inclusive) for system pools. The default value is 1. | +| `enableAutoScaling` | bool | `False` | `[True, False]` | Whether to enable auto-scaler | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableEncryptionAtHost` | bool | `False` | `[True, False]` | This is only supported on certain VM sizes and in certain Azure regions. For more information, see: /azure/aks/enable-host-encryption | +| `enableFIPS` | bool | `False` | `[True, False]` | See Add a FIPS-enabled node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool-preview) for more details. | +| `enableNodePublicIP` | bool | `False` | `[True, False]` | Some scenarios may require nodes in a node pool to receive their own dedicated public IP addresses. A common scenario is for gaming workloads, where a console needs to make a direct connection to a cloud virtual machine to minimize hops. For more information see assigning a public IP per node (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools). The default is false. | +| `enableUltraSSD` | bool | `False` | `[True, False]` | Whether to enable UltraSSD | +| `gpuInstanceProfile` | string | `''` | `[MIG1g, MIG2g, MIG3g, MIG4g, MIG7g, ]` | GPUInstanceProfile to be used to specify GPU MIG instance profile for supported GPU VM SKU. | +| `kubeletDiskType` | string | `''` | | Determines the placement of emptyDir volumes, container runtime data root, and Kubelet ephemeral storage. | +| `maxCount` | int | `-1` | | The maximum number of nodes for auto-scaling | +| `maxPods` | int | `-1` | | The maximum number of pods that can run on a node. | +| `maxSurge` | string | `''` | | This can either be set to an integer (e.g. "5") or a percentage (e.g. "50%"). If a percentage is specified, it is the percentage of the total agent pool size at the time of the upgrade. For percentages, fractional nodes are rounded up. If not specified, the default is 1. For more information, including best practices, see: /azure/aks/upgrade-cluster#customize-node-surge-upgrade | +| `minCount` | int | `-1` | | The minimum number of nodes for auto-scaling | +| `mode` | string | `''` | | A cluster must have at least one "System" Agent Pool at all times. For additional information on agent pool restrictions and best practices, see: /azure/aks/use-system-pools | +| `nodeLabels` | object | `{object}` | | The node labels to be persisted across all nodes in agent pool. | +| `nodePublicIpPrefixId` | string | `''` | | ResourceId of the node PublicIPPrefix | +| `nodeTaints` | array | `[]` | | The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. | +| `orchestratorVersion` | string | `''` | | As a best practice, you should upgrade all node pools in an AKS cluster to the same Kubernetes version. The node pool version must have the same major version as the control plane. The node pool minor version must be within two minor versions of the control plane version. The node pool version cannot be greater than the control plane version. For more information see upgrading a node pool (https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#upgrade-a-node-pool). | +| `osDiskSizeGB` | int | `0` | | OS Disk Size in GB to be used to specify the disk size for every machine in the master/agent pool. If you specify 0, it will apply the default osDisk size according to the vmSize specified. | +| `osDiskType` | string | `''` | `[Ephemeral, Managed, ]` | The default is "Ephemeral" if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, defaults to "Managed". May not be changed after creation. For more information see Ephemeral OS (https://docs.microsoft.com/en-us/azure/aks/cluster-configuration#ephemeral-os). | +| `osSku` | string | `''` | `[CBLMariner, Ubuntu, ]` | Specifies an OS SKU. This value must not be specified if OSType is Windows. | +| `osType` | string | `'Linux'` | `[Linux, Windows]` | The operating system type. The default is Linux. | +| `podSubnetId` | string | `''` | | Subnet ID for the pod IPs. If omitted, pod IPs are statically assigned on the node subnet (see vnetSubnetID for more details). This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} | +| `proximityPlacementGroupId` | string | `''` | | The ID for the Proximity Placement Group. | +| `scaleDownMode` | string | `'Delete'` | `[Deallocate, Delete]` | Describes how VMs are added to or removed from Agent Pools. See billing states (https://docs.microsoft.com/en-us/azure/virtual-machines/states-billing). | +| `scaleSetEvictionPolicy` | string | `'Delete'` | `[Deallocate, Delete]` | The eviction policy specifies what to do with the VM when it is evicted. The default is Delete. For more information about eviction see spot VMs | +| `scaleSetPriority` | string | `''` | `[Regular, Spot, ]` | The Virtual Machine Scale Set priority. | +| `sourceResourceId` | string | `''` | | This is the ARM ID of the source object to be used to create the target object. | +| `spotMaxPrice` | int | `-1` | | Possible values are any decimal value greater than zero or -1 which indicates the willingness to pay any on-demand price. For more details on spot pricing, see spot VMs pricing (https://docs.microsoft.com/en-us/azure/virtual-machines/spot-vms#pricing) | +| `tags` | object | `{object}` | | Tags of the resource. | +| `type` | string | `''` | | The type of Agent Pool. | +| `vmSize` | string | `'Standard_D2s_v3'` | | VM size. VM size availability varies by region. If a node contains insufficient compute resources (memory, cpu, etc) pods might fail to run correctly. For more details on restricted VM sizes, see: /azure/aks/quotas-skus-regions | +| `vnetSubnetId` | string | `''` | | Node Subnet ID. If this is not specified, a VNET and subnet will be generated and used. If no podSubnetID is specified, this applies to nodes and pods, otherwise it applies to just nodes. This is of the form: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} | +| `workloadRuntime` | string | `''` | | Determines the type of workload a node can run. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the agent pool | +| `resourceGroupName` | string | The resource group the agent pool was deployed into. | +| `resourceId` | string | The resource ID of the agent pool | + +## Template references + +- [Managedclusters/Agentpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerService/2021-08-01/managedClusters/agentPools) diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/version.json b/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/agentPools/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/carml/1.0.1/Microsoft.ContainerService/managedClusters/deploy.bicep b/carml/1.0.1/Microsoft.ContainerService/managedClusters/deploy.bicep new file mode 100644 index 000000000..555b60d13 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/deploy.bicep @@ -0,0 +1,572 @@ +@description('Required. Specifies the name of the AKS cluster.') +param name string + +@description('Optional. Specifies the location of AKS cluster. It picks up Resource Group\'s location by default.') +param location string = resourceGroup().location + +@description('Optional. Specifies the DNS prefix specified when creating the managed cluster.') +param aksClusterDnsPrefix string = name + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Specifies the network plugin used for building Kubernetes network. - azure or kubenet.') +@allowed([ + '' + 'azure' + 'kubenet' +]) +param aksClusterNetworkPlugin string = '' + +@description('Optional. Specifies the network policy used for building Kubernetes network. - calico or azure') +@allowed([ + '' + 'azure' + 'calico' +]) +param aksClusterNetworkPolicy string = '' + +@description('Optional. Specifies the CIDR notation IP range from which to assign pod IPs when kubenet is used.') +param aksClusterPodCidr string = '' + +@description('Optional. A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges.') +param aksClusterServiceCidr string = '' + +@description('Optional. Specifies the IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr.') +param aksClusterDnsServiceIP string = '' + +@description('Optional. Specifies the CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range.') +param aksClusterDockerBridgeCidr string = '' + +@description('Optional. Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools.') +@allowed([ + 'basic' + 'standard' +]) +param aksClusterLoadBalancerSku string = 'standard' + +@description('Optional. Outbound IP Count for the Load balancer.') +param managedOutboundIPCount int = 0 + +@description('Optional. Specifies outbound (egress) routing method. - loadBalancer or userDefinedRouting.') +@allowed([ + 'loadBalancer' + 'userDefinedRouting' +]) +param aksClusterOutboundType string = 'loadBalancer' + +@description('Optional. Tier of a managed cluster SKU. - Free or Paid') +@allowed([ + 'Free' + 'Paid' +]) +param aksClusterSkuTier string = 'Free' + +@description('Optional. Version of Kubernetes specified when creating the managed cluster.') +param aksClusterKubernetesVersion string = '' + +@description('Optional. Specifies the administrator username of Linux virtual machines.') +param aksClusterAdminUsername string = 'azureuser' + +@description('Optional. Specifies the SSH RSA public key string for the Linux nodes.') +param aksClusterSshPublicKey string = '' + +@description('Optional. Information about a service principal identity for the cluster to use for manipulating Azure APIs.') +param aksServicePrincipalProfile object = {} + +@description('Optional. The client AAD application ID.') +param aadProfileClientAppID string = '' + +@description('Optional. The server AAD application ID.') +param aadProfileServerAppID string = '' + +@description('Optional. The server AAD application secret.') +param aadProfileServerAppSecret string = '' + +@description('Optional. Specifies the tenant ID of the Azure Active Directory used by the AKS cluster for authentication.') +param aadProfileTenantId string = subscription().tenantId + +@description('Optional. Specifies the AAD group object IDs that will have admin role of the cluster.') +param aadProfileAdminGroupObjectIDs array = [] + +@description('Optional. Specifies whether to enable managed AAD integration.') +param aadProfileManaged bool = true + +@description('Optional. Specifies whether to enable Azure RBAC for Kubernetes authorization.') +param aadProfileEnableAzureRBAC bool = true + +@description('Optional. If set to true, getting static credentials will be disabled for this cluster. This must only be used on Managed Clusters that are AAD enabled.') +param disableLocalAccounts bool = false + +@description('Optional. Name of the resource group containing agent pool nodes.') +param nodeResourceGroup string = '${resourceGroup().name}_aks_${name}_nodes' + +@description('Optional. IP ranges are specified in CIDR format, e.g. 137.117.106.88/29. This feature is not compatible with clusters that use Public IP Per Node, or clusters that are using a Basic Load Balancer.') +param authorizedIPRanges array = [] + +@description('Optional. Whether to disable run command for the cluster or not.') +param disableRunCommand bool = false + +@description('Optional. Specifies whether to create the cluster as a private cluster or not.') +param enablePrivateCluster bool = false + +@description('Optional. Whether to create additional public FQDN for private cluster or not.') +param enablePrivateClusterPublicFQDN bool = false + +@description('Optional. If AKS will create a Private DNS Zone in the Node Resource Group.') +param usePrivateDNSZone bool = false + +@description('Required. Properties of the primary agent pool.') +param primaryAgentPoolProfile array + +@description('Optional. Define one or more secondary/additional agent pools') +param agentPools array = [] + +@description('Optional. Specifies whether the httpApplicationRouting add-on is enabled or not.') +param httpApplicationRoutingEnabled bool = false + +@description('Optional. Specifies whether the aciConnectorLinux add-on is enabled or not.') +param aciConnectorLinuxEnabled bool = false + +@description('Optional. Specifies whether the azurepolicy add-on is enabled or not.') +param azurePolicyEnabled bool = true + +@description('Optional. Specifies the azure policy version to use.') +param azurePolicyVersion string = 'v2' + +@description('Optional. Specifies whether the kubeDashboard add-on is enabled or not.') +param kubeDashboardEnabled bool = false + +@description('Optional. Specifies whether the KeyvaultSecretsProvider add-on is enabled or not.') +param enableKeyvaultSecretsProvider bool = false + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies whether the KeyvaultSecretsProvider add-on uses secret rotation.') +param enableSecretRotation string = 'false' + +@description('Optional. Specifies the scan interval of the auto-scaler of the AKS cluster.') +param autoScalerProfileScanInterval string = '10s' + +@description('Optional. Specifies the scale down delay after add of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownDelayAfterAdd string = '10m' + +@description('Optional. Specifies the scale down delay after delete of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownDelayAfterDelete string = '20s' + +@description('Optional. Specifies scale down delay after failure of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownDelayAfterFailure string = '3m' + +@description('Optional. Specifies the scale down unneeded time of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownUnneededTime string = '10m' + +@description('Optional. Specifies the scale down unready time of the auto-scaler of the AKS cluster.') +param autoScalerProfileScaleDownUnreadyTime string = '20m' + +@description('Optional. Specifies the utilization threshold of the auto-scaler of the AKS cluster.') +param autoScalerProfileUtilizationThreshold string = '0.5' + +@description('Optional. Specifies the max graceful termination time interval in seconds for the auto-scaler of the AKS cluster.') +param autoScalerProfileMaxGracefulTerminationSec string = '600' + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies the balance of similar node groups for the auto-scaler of the AKS cluster.') +param autoScalerProfileBalanceSimilarNodeGroups string = 'false' + +@allowed([ + 'least-waste' + 'most-pods' + 'priority' + 'random' +]) +@description('Optional. Specifies the expand strategy for the auto-scaler of the AKS cluster.') +param autoScalerProfileExpander string = 'random' + +@description('Optional. Specifies the maximum empty bulk delete for the auto-scaler of the AKS cluster.') +param autoScalerProfileMaxEmptyBulkDelete string = '10' + +@description('Optional. Specifies the maximum node provisioning time for the auto-scaler of the AKS cluster. Values must be an integer followed by an "m". No unit of time other than minutes (m) is supported.') +param autoScalerProfileMaxNodeProvisionTime string = '15m' + +@description('Optional. Specifies the mximum total unready percentage for the auto-scaler of the AKS cluster. The maximum is 100 and the minimum is 0.') +param autoScalerProfileMaxTotalUnreadyPercentage string = '45' + +@description('Optional. For scenarios like burst/batch scale where you do not want CA to act before the kubernetes scheduler could schedule all the pods, you can tell CA to ignore unscheduled pods before they are a certain age. Values must be an integer followed by a unit ("s" for seconds, "m" for minutes, "h" for hours, etc).') +param autoScalerProfileNewPodScaleUpDelay string = '0s' + +@description('Optional. Specifies the ok total unready count for the auto-scaler of the AKS cluster.') +param autoScalerProfileOkTotalUnreadyCount string = '3' + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies if nodes with local storage should be skipped for the auto-scaler of the AKS cluster.') +param autoScalerProfileSkipNodesWithLocalStorage string = 'true' + +@allowed([ + 'false' + 'true' +]) +@description('Optional. Specifies if nodes with system pods should be skipped for the auto-scaler of the AKS cluster.') +param autoScalerProfileSkipNodesWithSystemPods string = 'true' + +@description('Optional. Running in Kubenet is disabled by default due to the security related nature of AAD Pod Identity and the risks of IP spoofing.') +param podIdentityProfileAllowNetworkPluginKubenet bool = false + +@description('Optional. Whether the pod identity addon is enabled.') +param podIdentityProfileEnable bool = false + +@description('Optional. The pod identities to use in the cluster.') +param podIdentityProfileUserAssignedIdentities array = [] + +@description('Optional. The pod identity exceptions to allow.') +param podIdentityProfileUserAssignedIdentityExceptions array = [] + +@description('Optional. Whether the The OIDC issuer profile of the Managed Cluster is enabled.') +param enableOidcIssuerProfile bool = false + +@description('Optional. Whether to enable Azure Defender.') +param enableAzureDefender bool = false + +@description('Optional. Whether to enable Kubernetes pod security policy.') +param enablePodSecurityPolicy bool = false + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Specifies whether the OMS agent is enabled.') +param omsAgentEnabled bool = true + +@description('Optional. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'kube-apiserver' + 'kube-audit' + 'kube-controller-manager' + 'kube-scheduler' + 'cluster-autoscaler' +]) +param diagnosticLogCategoriesToEnable array = [ + 'kube-apiserver' + 'kube-audit' + 'kube-controller-manager' + 'kube-scheduler' + 'cluster-autoscaler' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? 'SystemAssigned' : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var aksClusterLinuxProfile = { + adminUsername: aksClusterAdminUsername + ssh: { + publicKeys: [ + { + keyData: aksClusterSshPublicKey + } + ] + } +} + +var lbProfile = { + managedOutboundIPs: { + count: managedOutboundIPCount + } + effectiveOutboundIPs: [] +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2022-01-01' = { + name: name + location: location + tags: (empty(tags) ? null : tags) + identity: identity + sku: { + name: 'Basic' + tier: aksClusterSkuTier + } + properties: { + kubernetesVersion: (empty(aksClusterKubernetesVersion) ? null : aksClusterKubernetesVersion) + dnsPrefix: aksClusterDnsPrefix + agentPoolProfiles: primaryAgentPoolProfile + linuxProfile: (empty(aksClusterSshPublicKey) ? null : aksClusterLinuxProfile) + servicePrincipalProfile: (empty(aksServicePrincipalProfile) ? null : aksServicePrincipalProfile) + addonProfiles: { + httpApplicationRouting: { + enabled: httpApplicationRoutingEnabled + } + omsagent: { + enabled: omsAgentEnabled && !empty(monitoringWorkspaceId) + config: { + logAnalyticsWorkspaceResourceID: !empty(monitoringWorkspaceId) ? any(monitoringWorkspaceId) : null + } + } + aciConnectorLinux: { + enabled: aciConnectorLinuxEnabled + } + azurepolicy: { + enabled: azurePolicyEnabled + config: { + version: azurePolicyVersion + } + } + kubeDashboard: { + enabled: kubeDashboardEnabled + } + azureKeyvaultSecretsProvider: { + enabled: enableKeyvaultSecretsProvider + config: { + enableSecretRotation: enableSecretRotation + } + } + } + oidcIssuerProfile: enableOidcIssuerProfile ? { + enabled: enableOidcIssuerProfile + } : null + enableRBAC: aadProfileEnableAzureRBAC + disableLocalAccounts: disableLocalAccounts + nodeResourceGroup: nodeResourceGroup + enablePodSecurityPolicy: enablePodSecurityPolicy + networkProfile: { + networkPlugin: !empty(aksClusterNetworkPlugin) ? any(aksClusterNetworkPlugin) : null + networkPolicy: !empty(aksClusterNetworkPolicy) ? any(aksClusterNetworkPolicy) : null + podCidr: !empty(aksClusterPodCidr) ? aksClusterPodCidr : null + serviceCidr: !empty(aksClusterServiceCidr) ? aksClusterServiceCidr : null + dnsServiceIP: !empty(aksClusterDnsServiceIP) ? aksClusterDnsServiceIP : null + dockerBridgeCidr: !empty(aksClusterDockerBridgeCidr) ? aksClusterDockerBridgeCidr : null + outboundType: aksClusterOutboundType + loadBalancerSku: aksClusterLoadBalancerSku + loadBalancerProfile: managedOutboundIPCount != 0 ? lbProfile : null + } + aadProfile: { + clientAppID: aadProfileClientAppID + serverAppID: aadProfileServerAppID + serverAppSecret: aadProfileServerAppSecret + managed: aadProfileManaged + enableAzureRBAC: aadProfileEnableAzureRBAC + adminGroupObjectIDs: aadProfileAdminGroupObjectIDs + tenantID: aadProfileTenantId + } + autoScalerProfile: { + 'balance-similar-node-groups': autoScalerProfileBalanceSimilarNodeGroups + 'expander': autoScalerProfileExpander + 'max-empty-bulk-delete': autoScalerProfileMaxEmptyBulkDelete + 'max-graceful-termination-sec': autoScalerProfileMaxGracefulTerminationSec + 'max-node-provision-time': autoScalerProfileMaxNodeProvisionTime + 'max-total-unready-percentage': autoScalerProfileMaxTotalUnreadyPercentage + 'new-pod-scale-up-delay': autoScalerProfileNewPodScaleUpDelay + 'ok-total-unready-count': autoScalerProfileOkTotalUnreadyCount + 'scale-down-delay-after-add': autoScalerProfileScaleDownDelayAfterAdd + 'scale-down-delay-after-delete': autoScalerProfileScaleDownDelayAfterDelete + 'scale-down-delay-after-failure': autoScalerProfileScaleDownDelayAfterFailure + 'scale-down-unneeded-time': autoScalerProfileScaleDownUnneededTime + 'scale-down-unready-time': autoScalerProfileScaleDownUnreadyTime + 'scale-down-utilization-threshold': autoScalerProfileUtilizationThreshold + 'scan-interval': autoScalerProfileScanInterval + 'skip-nodes-with-local-storage': autoScalerProfileSkipNodesWithLocalStorage + 'skip-nodes-with-system-pods': autoScalerProfileSkipNodesWithSystemPods + } + apiServerAccessProfile: { + authorizedIPRanges: authorizedIPRanges + disableRunCommand: disableRunCommand + enablePrivateCluster: enablePrivateCluster + enablePrivateClusterPublicFQDN: enablePrivateClusterPublicFQDN + privateDNSZone: usePrivateDNSZone ? 'system' : '' + } + podIdentityProfile: { + allowNetworkPluginKubenet: podIdentityProfileAllowNetworkPluginKubenet + enabled: podIdentityProfileEnable + userAssignedIdentities: podIdentityProfileUserAssignedIdentities + userAssignedIdentityExceptions: podIdentityProfileUserAssignedIdentityExceptions + } + securityProfile: enableAzureDefender ? { + azureDefender: { + enabled: enableAzureDefender + logAnalyticsWorkspaceResourceId: !empty(monitoringWorkspaceId) ? monitoringWorkspaceId : null + } + } : null + } +} + +module managedCluster_agentPools 'agentPools/deploy.bicep' = [for (agentPool, index) in agentPools: { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-AgentPool-${index}' + params: { + managedClusterName: managedCluster.name + name: agentPool.name + availabilityZones: contains(agentPool, 'availabilityZones') ? agentPool.availabilityZones : [] + count: contains(agentPool, 'count') ? agentPool.count : 1 + sourceResourceId: contains(agentPool, 'sourceResourceId') ? agentPool.sourceResourceId : '' + enableAutoScaling: contains(agentPool, 'enableAutoScaling') ? agentPool.enableAutoScaling : false + enableEncryptionAtHost: contains(agentPool, 'enableEncryptionAtHost') ? agentPool.enableEncryptionAtHost : false + enableFIPS: contains(agentPool, 'enableFIPS') ? agentPool.enableFIPS : false + enableNodePublicIP: contains(agentPool, 'enableNodePublicIP') ? agentPool.enableNodePublicIP : false + enableUltraSSD: contains(agentPool, 'enableUltraSSD') ? agentPool.enableUltraSSD : false + gpuInstanceProfile: contains(agentPool, 'gpuInstanceProfile') ? agentPool.gpuInstanceProfile : '' + kubeletDiskType: contains(agentPool, 'kubeletDiskType') ? agentPool.kubeletDiskType : '' + maxCount: contains(agentPool, 'maxCount') ? agentPool.maxCount : -1 + maxPods: contains(agentPool, 'maxPods') ? agentPool.maxPods : -1 + minCount: contains(agentPool, 'minCount') ? agentPool.minCount : -1 + mode: contains(agentPool, 'mode') ? agentPool.mode : '' + nodeLabels: contains(agentPool, 'nodeLabels') ? agentPool.nodeLabels : {} + nodePublicIpPrefixId: contains(agentPool, 'nodePublicIpPrefixId') ? agentPool.nodePublicIpPrefixId : '' + nodeTaints: contains(agentPool, 'nodeTaints') ? agentPool.nodeTaints : [] + orchestratorVersion: contains(agentPool, 'orchestratorVersion') ? agentPool.orchestratorVersion : '' + osDiskSizeGB: contains(agentPool, 'osDiskSizeGB') ? agentPool.osDiskSizeGB : -1 + osDiskType: contains(agentPool, 'osDiskType') ? agentPool.osDiskType : '' + osSku: contains(agentPool, 'osSku') ? agentPool.osSku : '' + osType: contains(agentPool, 'osType') ? agentPool.osType : 'Linux' + podSubnetId: contains(agentPool, 'podSubnetId') ? agentPool.podSubnetId : '' + proximityPlacementGroupId: contains(agentPool, 'proximityPlacementGroupId') ? agentPool.proximityPlacementGroupId : '' + scaleDownMode: contains(agentPool, 'scaleDownMode') ? agentPool.scaleDownMode : 'Delete' + scaleSetEvictionPolicy: contains(agentPool, 'scaleSetEvictionPolicy') ? agentPool.scaleSetEvictionPolicy : 'Delete' + scaleSetPriority: contains(agentPool, 'scaleSetPriority') ? agentPool.scaleSetPriority : '' + spotMaxPrice: contains(agentPool, 'spotMaxPrice') ? agentPool.spotMaxPrice : -1 + tags: contains(agentPool, 'tags') ? agentPool.tags : {} + type: contains(agentPool, 'type') ? agentPool.type : '' + maxSurge: contains(agentPool, 'maxSurge') ? agentPool.maxSurge : '' + vmSize: contains(agentPool, 'vmSize') ? agentPool.vmSize : 'Standard_D2s_v3' + vnetSubnetId: contains(agentPool, 'vnetSubnetId') ? agentPool.vnetSubnetId : '' + workloadRuntime: contains(agentPool, 'workloadRuntime') ? agentPool.workloadRuntime : '' + } +}] + +resource managedCluster_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${managedCluster.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: managedCluster +} + +resource managedCluster_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: managedCluster +} + +module managedCluster_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ManagedCluster-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: managedCluster.id + } +}] + +@description('The resource ID of the managed cluster') +output resourceId string = managedCluster.id + +@description('The resource group the managed cluster was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the managed cluster') +output name string = managedCluster.name + +@description('The control plane FQDN of the managed cluster') +output controlPlaneFQDN string = enablePrivateCluster ? managedCluster.properties.privateFQDN : managedCluster.properties.fqdn + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(managedCluster.identity, 'principalId') ? managedCluster.identity.principalId : '' + +@description('The Object ID of the AKS identity.') +output kubeletidentityObjectId string = contains(managedCluster.properties, 'identityProfile') ? contains(managedCluster.properties.identityProfile, 'kubeletidentity') ? managedCluster.properties.identityProfile.kubeletidentity.objectId : '' : '' + +@description('The Object ID of the OMS agent identity.') +output omsagentIdentityObjectId string = contains(managedCluster.properties, 'addonProfiles') ? contains(managedCluster.properties.addonProfiles, 'omsagent') ? contains(managedCluster.properties.addonProfiles.omsagent, 'identity') ? managedCluster.properties.addonProfiles.omsagent.identity.objectId : '' : '' : '' diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/readme.md b/carml/1.0.1/Microsoft.ContainerService/managedClusters/readme.md new file mode 100644 index 000000000..50c0d9f61 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/readme.md @@ -0,0 +1,257 @@ +# Azure Kubernetes Services `[Microsoft.ContainerService/managedClusters]` + +This module deploys Azure Kubernetes Cluster (AKS). + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ContainerService/managedClusters` | 2022-01-01 | +| `Microsoft.ContainerService/managedClusters/agentPools` | 2021-08-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the AKS cluster. | +| `primaryAgentPoolProfile` | array | Properties of the primary agent pool. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `aadProfileAdminGroupObjectIDs` | array | `[]` | | Specifies the AAD group object IDs that will have admin role of the cluster. | +| `aadProfileClientAppID` | string | `''` | | The client AAD application ID. | +| `aadProfileEnableAzureRBAC` | bool | `True` | | Specifies whether to enable Azure RBAC for Kubernetes authorization. | +| `aadProfileManaged` | bool | `True` | | Specifies whether to enable managed AAD integration. | +| `aadProfileServerAppID` | string | `''` | | The server AAD application ID. | +| `aadProfileServerAppSecret` | string | `''` | | The server AAD application secret. | +| `aadProfileTenantId` | string | `[subscription().tenantId]` | | Specifies the tenant ID of the Azure Active Directory used by the AKS cluster for authentication. | +| `aciConnectorLinuxEnabled` | bool | `False` | | Specifies whether the aciConnectorLinux add-on is enabled or not. | +| `agentPools` | _[agentPools](agentPools/readme.md)_ array | `[]` | | Define one or more secondary/additional agent pools | +| `aksClusterAdminUsername` | string | `'azureuser'` | | Specifies the administrator username of Linux virtual machines. | +| `aksClusterDnsPrefix` | string | `[parameters('name')]` | | Specifies the DNS prefix specified when creating the managed cluster. | +| `aksClusterDnsServiceIP` | string | `''` | | Specifies the IP address assigned to the Kubernetes DNS service. It must be within the Kubernetes service address range specified in serviceCidr. | +| `aksClusterDockerBridgeCidr` | string | `''` | | Specifies the CIDR notation IP range assigned to the Docker bridge network. It must not overlap with any Subnet IP ranges or the Kubernetes service address range. | +| `aksClusterKubernetesVersion` | string | `''` | | Version of Kubernetes specified when creating the managed cluster. | +| `aksClusterLoadBalancerSku` | string | `'standard'` | `[basic, standard]` | Specifies the sku of the load balancer used by the virtual machine scale sets used by nodepools. | +| `aksClusterNetworkPlugin` | string | `''` | `[, azure, kubenet]` | Specifies the network plugin used for building Kubernetes network. - azure or kubenet. | +| `aksClusterNetworkPolicy` | string | `''` | `[, azure, calico]` | Specifies the network policy used for building Kubernetes network. - calico or azure | +| `aksClusterOutboundType` | string | `'loadBalancer'` | `[loadBalancer, userDefinedRouting]` | Specifies outbound (egress) routing method. - loadBalancer or userDefinedRouting. | +| `aksClusterPodCidr` | string | `''` | | Specifies the CIDR notation IP range from which to assign pod IPs when kubenet is used. | +| `aksClusterServiceCidr` | string | `''` | | A CIDR notation IP range from which to assign service cluster IPs. It must not overlap with any Subnet IP ranges. | +| `aksClusterSkuTier` | string | `'Free'` | `[Free, Paid]` | Tier of a managed cluster SKU. - Free or Paid | +| `aksClusterSshPublicKey` | string | `''` | | Specifies the SSH RSA public key string for the Linux nodes. | +| `aksServicePrincipalProfile` | object | `{object}` | | Information about a service principal identity for the cluster to use for manipulating Azure APIs. | +| `authorizedIPRanges` | array | `[]` | | IP ranges are specified in CIDR format, e.g. 137.117.106.88/29. This feature is not compatible with clusters that use Public IP Per Node, or clusters that are using a Basic Load Balancer. | +| `autoScalerProfileBalanceSimilarNodeGroups` | string | `'false'` | `[false, true]` | Specifies the balance of similar node groups for the auto-scaler of the AKS cluster. | +| `autoScalerProfileExpander` | string | `'random'` | `[least-waste, most-pods, priority, random]` | Specifies the expand strategy for the auto-scaler of the AKS cluster. | +| `autoScalerProfileMaxEmptyBulkDelete` | string | `'10'` | | Specifies the maximum empty bulk delete for the auto-scaler of the AKS cluster. | +| `autoScalerProfileMaxGracefulTerminationSec` | string | `'600'` | | Specifies the max graceful termination time interval in seconds for the auto-scaler of the AKS cluster. | +| `autoScalerProfileMaxNodeProvisionTime` | string | `'15m'` | | Specifies the maximum node provisioning time for the auto-scaler of the AKS cluster. Values must be an integer followed by an "m". No unit of time other than minutes (m) is supported. | +| `autoScalerProfileMaxTotalUnreadyPercentage` | string | `'45'` | | Specifies the mximum total unready percentage for the auto-scaler of the AKS cluster. The maximum is 100 and the minimum is 0. | +| `autoScalerProfileNewPodScaleUpDelay` | string | `'0s'` | | For scenarios like burst/batch scale where you do not want CA to act before the kubernetes scheduler could schedule all the pods, you can tell CA to ignore unscheduled pods before they are a certain age. Values must be an integer followed by a unit ("s" for seconds, "m" for minutes, "h" for hours, etc). | +| `autoScalerProfileOkTotalUnreadyCount` | string | `'3'` | | Specifies the ok total unready count for the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownDelayAfterAdd` | string | `'10m'` | | Specifies the scale down delay after add of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownDelayAfterDelete` | string | `'20s'` | | Specifies the scale down delay after delete of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownDelayAfterFailure` | string | `'3m'` | | Specifies scale down delay after failure of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownUnneededTime` | string | `'10m'` | | Specifies the scale down unneeded time of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScaleDownUnreadyTime` | string | `'20m'` | | Specifies the scale down unready time of the auto-scaler of the AKS cluster. | +| `autoScalerProfileScanInterval` | string | `'10s'` | | Specifies the scan interval of the auto-scaler of the AKS cluster. | +| `autoScalerProfileSkipNodesWithLocalStorage` | string | `'true'` | `[false, true]` | Specifies if nodes with local storage should be skipped for the auto-scaler of the AKS cluster. | +| `autoScalerProfileSkipNodesWithSystemPods` | string | `'true'` | `[false, true]` | Specifies if nodes with system pods should be skipped for the auto-scaler of the AKS cluster. | +| `autoScalerProfileUtilizationThreshold` | string | `'0.5'` | | Specifies the utilization threshold of the auto-scaler of the AKS cluster. | +| `azurePolicyEnabled` | bool | `True` | | Specifies whether the azurepolicy add-on is enabled or not. | +| `azurePolicyVersion` | string | `'v2'` | | Specifies the azure policy version to use. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[kube-apiserver, kube-audit, kube-controller-manager, kube-scheduler, cluster-autoscaler]` | `[kube-apiserver, kube-audit, kube-controller-manager, kube-scheduler, cluster-autoscaler]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disableLocalAccounts` | bool | `False` | | If set to true, getting static credentials will be disabled for this cluster. This must only be used on Managed Clusters that are AAD enabled. | +| `disableRunCommand` | bool | `False` | | Whether to disable run command for the cluster or not. | +| `enableAzureDefender` | bool | `False` | | Whether to enable Azure Defender. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableKeyvaultSecretsProvider` | bool | `False` | | Specifies whether the KeyvaultSecretsProvider add-on is enabled or not. | +| `enableOidcIssuerProfile` | bool | `False` | | Whether the The OIDC issuer profile of the Managed Cluster is enabled. | +| `enablePodSecurityPolicy` | bool | `False` | | Whether to enable Kubernetes pod security policy. | +| `enablePrivateCluster` | bool | `False` | | Specifies whether to create the cluster as a private cluster or not. | +| `enablePrivateClusterPublicFQDN` | bool | `False` | | Whether to create additional public FQDN for private cluster or not. | +| `enableSecretRotation` | string | `'false'` | `[false, true]` | Specifies whether the KeyvaultSecretsProvider add-on uses secret rotation. | +| `httpApplicationRoutingEnabled` | bool | `False` | | Specifies whether the httpApplicationRouting add-on is enabled or not. | +| `kubeDashboardEnabled` | bool | `False` | | Specifies whether the kubeDashboard add-on is enabled or not. | +| `location` | string | `[resourceGroup().location]` | | Specifies the location of AKS cluster. It picks up Resource Group's location by default. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managedOutboundIPCount` | int | `0` | | Outbound IP Count for the Load balancer. | +| `monitoringWorkspaceId` | string | `''` | | Resource ID of the monitoring log analytics workspace. | +| `nodeResourceGroup` | string | `[format('{0}_aks_{1}_nodes', resourceGroup().name, parameters('name'))]` | | Name of the resource group containing agent pool nodes. | +| `omsAgentEnabled` | bool | `True` | | Specifies whether the OMS agent is enabled. | +| `podIdentityProfileAllowNetworkPluginKubenet` | bool | `False` | | Running in Kubenet is disabled by default due to the security related nature of AAD Pod Identity and the risks of IP spoofing. | +| `podIdentityProfileEnable` | bool | `False` | | Whether the pod identity addon is enabled. | +| `podIdentityProfileUserAssignedIdentities` | array | `[]` | | The pod identities to use in the cluster. | +| `podIdentityProfileUserAssignedIdentityExceptions` | array | `[]` | | The pod identity exceptions to allow. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `usePrivateDNSZone` | bool | `False` | | If AKS will create a Private DNS Zone in the Node Resource Group. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `identity` + +See also + +```json +"identity": { + "value": { + "type": "string", + "userAssignedIdentities": {} + } +} +``` + +### Parameter Usage: `aksServicePrincipalProfile` + +See also + +```json +"aksServicePrincipalProfile": { + "value": { + "clientId": "string", + "secret": "string" + } +} +``` + +### Parameter Usage: `primaryAgentPoolProfile` + +Provide values for primary agent pool as needed. +For available properties check + +```json +"primaryAgentPoolProfile": { + "value": [ + { + "name": "poolname", + "vmSize": "Standard_DS3_v2", + "osDiskSizeGB": 128, + "count": 2, + "osType": "Linux", + "maxCount": 5, + "minCount": 1, + "enableAutoScaling": true, + "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", + "nodeLabels": {}, + "nodeTaints": [ + "CriticalAddonsOnly=true:NoSchedule" + ], + "type": "VirtualMachineScaleSets", + "availabilityZones": [ + "1", + "2", + "3" + ], + "maxPods": 30, + "storageProfile": "ManagedDisks", + "mode": "System", + "vnetSubnetID": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/myRg/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet", + "tags": { + "Owner": "test.user@testcompany.com", + "BusinessUnit": "IaCs", + "Environment": "PROD", + "Region": "USEast" + } + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `controlPlaneFQDN` | string | The control plane FQDN of the managed cluster | +| `kubeletidentityObjectId` | string | The Object ID of the AKS identity. | +| `name` | string | The name of the managed cluster | +| `omsagentIdentityObjectId` | string | The Object ID of the OMS agent identity. | +| `resourceGroupName` | string | The resource group the managed cluster was deployed into | +| `resourceId` | string | The resource ID of the managed cluster | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Managedclusters](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerService/2022-01-01/managedClusters) +- [Managedclusters/Agentpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ContainerService/2021-08-01/managedClusters/agentPools) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.ContainerService/managedClusters/version.json b/carml/1.0.1/Microsoft.ContainerService/managedClusters/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ContainerService/managedClusters/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/carml/1.0.1/Microsoft.DataFactory/factories/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.DataFactory/factories/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..1405220d5 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/.bicep/nested_rbac.bicep @@ -0,0 +1,54 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Data Factory Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(dataFactory.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: dataFactory +}] diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/.parameters/parameters.json b/carml/1.0.1/Microsoft.DataFactory/factories/.parameters/parameters.json new file mode 100644 index 000000000..8b5e31f73 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/.parameters/parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-adf-001" + }, + "managedVirtualNetworkName": { + "value": "default" + }, + "integrationRuntime": { + "value": { + "name": "AutoResolveIntegrationRuntime", + "type": "Managed", + "managedVirtualNetworkName": "default", + "typeProperties": { + "computeProperties": { + "location": "AutoResolve" + } + } + } + }, + "publicNetworkAccess": { + "value": true + }, + "gitConfigureLater": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/deploy.bicep b/carml/1.0.1/Microsoft.DataFactory/factories/deploy.bicep new file mode 100644 index 000000000..5a72915bc --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/deploy.bicep @@ -0,0 +1,226 @@ +@description('Required. The name of the Azure Factory to create') +param name string + +@description('Optional. The name of the Managed Virtual Network') +param managedVirtualNetworkName string = '' + +@description('Optional. The object for the configuration of a Integration Runtime') +param integrationRuntime object = {} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Enable or disable public network access.') +param publicNetworkAccess bool = true + +@description('Optional. Boolean to define whether or not to configure git during template deployment.') +param gitConfigureLater bool = true + +@description('Optional. Repository type - can be \'FactoryVSTSConfiguration\' or \'FactoryGitHubConfiguration\'. Default is \'FactoryVSTSConfiguration\'.') +param gitRepoType string = 'FactoryVSTSConfiguration' + +@description('Optional. The account name.') +param gitAccountName string = '' + +@description('Optional. The project name. Only relevant for \'FactoryVSTSConfiguration\'.') +param gitProjectName string = '' + +@description('Optional. The repository name.') +param gitRepositoryName string = '' + +@description('Optional. The collaboration branch name. Default is \'main\'.') +param gitCollaborationBranch string = 'main' + +@description('Optional. The root folder path name. Default is \'/\'.') +param gitRootFolder string = '/' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ActivityRuns' + 'PipelineRuns' + 'TriggerRuns' + 'SSISPackageEventMessages' + 'SSISPackageExecutableStatistics' + 'SSISPackageEventMessageContext' + 'SSISPackageExecutionComponentPhases' + 'SSISPackageExecutionDataStatistics' + 'SSISIntegrationRuntimeLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ActivityRuns' + 'PipelineRuns' + 'TriggerRuns' + 'SSISPackageEventMessages' + 'SSISPackageExecutableStatistics' + 'SSISPackageEventMessageContext' + 'SSISPackageExecutionComponentPhases' + 'SSISPackageExecutionDataStatistics' + 'SSISIntegrationRuntimeLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + repoConfiguration: bool(gitConfigureLater) ? null : json('{"type": "${gitRepoType}","accountName": "${gitAccountName}","repositoryName": "${gitRepositoryName}",${((gitRepoType == 'FactoryVSTSConfiguration') ? '"projectName": "${gitProjectName}",' : '')}"collaborationBranch": "${gitCollaborationBranch}","rootFolder": "${gitRootFolder}"}') + publicNetworkAccess: bool(publicNetworkAccess) ? 'Enabled' : 'Disabled' + } +} + +module dataFactory_managedVirtualNetwork 'managedVirtualNetwork/deploy.bicep' = if (!empty(managedVirtualNetworkName)) { + name: '${uniqueString(deployment().name, location)}-DataFactory-ManagedVNet' + params: { + name: managedVirtualNetworkName + dataFactoryName: dataFactory.name + } +} + +module dataFactory_integrationRuntime 'integrationRuntime/deploy.bicep' = if (!empty(integrationRuntime)) { + name: '${uniqueString(deployment().name, location)}-DataFactory-IntegrationRuntime' + params: { + dataFactoryName: dataFactory.name + name: integrationRuntime.name + type: integrationRuntime.type + managedVirtualNetworkName: contains(integrationRuntime, 'managedVirtualNetworkName') ? integrationRuntime.managedVirtualNetworkName : '' + typeProperties: integrationRuntime.typeProperties + } + dependsOn: [ + dataFactory_managedVirtualNetwork + ] +} + +resource dataFactory_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${dataFactory.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: dataFactory +} + +resource dataFactory_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: dataFactory +} + +module dataFactory_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DataFactory-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: dataFactory.id + } +}] + +@description('The Name of the Azure Data Factory instance.') +output name string = dataFactory.name + +@description('The Resource ID of the Data factory.') +output resourceId string = dataFactory.id + +@description('The name of the Resource Group with the Data factory.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(dataFactory.identity, 'principalId') ? dataFactory.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/deploy.bicep b/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/deploy.bicep new file mode 100644 index 000000000..8be80fda9 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/deploy.bicep @@ -0,0 +1,61 @@ +@description('Required. The name of the Azure Data Factory') +param dataFactoryName string + +@description('Required. The name of the Integration Runtime') +param name string + +@allowed([ + 'Managed' + 'SelfHosted' +]) +@description('Required. The type of Integration Runtime') +param type string + +@description('Optional. The name of the Managed Virtual Network if using type "Managed" ') +param managedVirtualNetworkName string = '' + +@description('Required. Integration Runtime type properties.') +param typeProperties object + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var managedVirtualNetwork_var = { + referenceName: type == 'Managed' ? managedVirtualNetworkName : null + type: type == 'Managed' ? 'ManagedVirtualNetworkReference' : null +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' existing = { + name: dataFactoryName +} + +resource integrationRuntime 'Microsoft.DataFactory/factories/integrationRuntimes@2018-06-01' = { + name: name + parent: dataFactory + properties: { + type: type + managedVirtualNetwork: type == 'Managed' ? managedVirtualNetwork_var : null + typeProperties: typeProperties + } +} + +@description('The name of the Resource Group the Integration Runtime was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Integration Runtime.') +output name string = integrationRuntime.name + +@description('The resource ID of the Integration Runtime.') +output resourceId string = integrationRuntime.id diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/readme.md b/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/readme.md new file mode 100644 index 000000000..5b0e9e761 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/readme.md @@ -0,0 +1,58 @@ +# Data Factory Integration RunTimes `[Microsoft.DataFactory/factories/integrationRuntime]` + +This module deploys a Managed or Self-Hosted Integration Runtime for an Azure Data Factory + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DataFactory/factories/integrationRuntimes` | 2018-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `dataFactoryName` | string | | The name of the Azure Data Factory | +| `name` | string | | The name of the Integration Runtime | +| `type` | string | `[Managed, SelfHosted]` | The type of Integration Runtime | +| `typeProperties` | object | | Integration Runtime type properties. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `managedVirtualNetworkName` | string | `''` | The name of the Managed Virtual Network if using type "Managed" | + + +### Parameter Usage: [`typeProperties`](https://docs.microsoft.com/en-us/azure/templates/microsoft.datafactory/factories/integrationruntimes?tabs=bicep#integrationruntime-objects) + +```json +"typeProperties": { + "value": { + "computeProperties": { + "location": "AutoResolve" + } + } +} + +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Integration Runtime. | +| `resourceGroupName` | string | The name of the Resource Group the Integration Runtime was created in. | +| `resourceId` | string | The resource ID of the Integration Runtime. | + +## Template references + +- [Factories/Integrationruntimes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/integrationRuntimes) diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/version.json b/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/integrationRuntime/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/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/deploy.bicep b/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/deploy.bicep new file mode 100644 index 000000000..d7bd38917 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/deploy.bicep @@ -0,0 +1,39 @@ +@description('Required. The name of the Azure Data Factory') +param dataFactoryName string + +@description('Required. The name of the Managed Virtual Network') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' existing = { + name: dataFactoryName +} + +resource managedVirtualNetwork 'Microsoft.DataFactory/factories/managedVirtualNetworks@2018-06-01' = { + name: name + parent: dataFactory + properties: {} +} + +@description('The name of the Resource Group the Managed Virtual Network was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the Managed Virtual Network.') +output name string = managedVirtualNetwork.name + +@description('The resource ID of the Managed Virtual Network.') +output resourceId string = managedVirtualNetwork.id diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/readme.md b/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/readme.md new file mode 100644 index 000000000..dd1e38377 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/readme.md @@ -0,0 +1,42 @@ +# Data Factory Managed Virtual Network `[Microsoft.DataFactory/factories/managedVirtualNetwork]` + +This module deploys a Managed Virtual Network for an Azure Data Factory + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DataFactory/factories/managedVirtualNetworks` | 2018-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `dataFactoryName` | string | The name of the Azure Data Factory | +| `name` | string | The name of the Managed Virtual Network | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Managed Virtual Network. | +| `resourceGroupName` | string | The name of the Resource Group the Managed Virtual Network was created in. | +| `resourceId` | string | The resource ID of the Managed Virtual Network. | + +## Template references + +- [Factories/Managedvirtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/managedVirtualNetworks) diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/version.json b/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/managedVirtualNetwork/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/carml/1.0.1/Microsoft.DataFactory/factories/readme.md b/carml/1.0.1/Microsoft.DataFactory/factories/readme.md new file mode 100644 index 000000000..9e06d795a --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/readme.md @@ -0,0 +1,130 @@ +# Data Factories `[Microsoft.DataFactory/factories]` + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DataFactory/factories` | 2018-06-01 | +| `Microsoft.DataFactory/factories/integrationRuntimes` | 2018-06-01 | +| `Microsoft.DataFactory/factories/managedVirtualNetworks` | 2018-06-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Azure Factory to create | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ActivityRuns, PipelineRuns, TriggerRuns, SSISPackageEventMessages, SSISPackageExecutableStatistics, SSISPackageEventMessageContext, SSISPackageExecutionComponentPhases, SSISPackageExecutionDataStatistics, SSISIntegrationRuntimeLogs]` | `[ActivityRuns, PipelineRuns, TriggerRuns, SSISPackageEventMessages, SSISPackageExecutableStatistics, SSISPackageEventMessageContext, SSISPackageExecutionComponentPhases, SSISPackageExecutionDataStatistics, SSISIntegrationRuntimeLogs]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `gitAccountName` | string | `''` | | The account name. | +| `gitCollaborationBranch` | string | `'main'` | | The collaboration branch name. Default is 'main'. | +| `gitConfigureLater` | bool | `True` | | Boolean to define whether or not to configure git during template deployment. | +| `gitProjectName` | string | `''` | | The project name. Only relevant for 'FactoryVSTSConfiguration'. | +| `gitRepositoryName` | string | `''` | | The repository name. | +| `gitRepoType` | string | `'FactoryVSTSConfiguration'` | | Repository type - can be 'FactoryVSTSConfiguration' or 'FactoryGitHubConfiguration'. Default is 'FactoryVSTSConfiguration'. | +| `gitRootFolder` | string | `'/'` | | The root folder path name. Default is '/'. | +| `integrationRuntime` | _[integrationRuntime](integrationRuntime/readme.md)_ object | `{object}` | | The object for the configuration of a Integration Runtime | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managedVirtualNetworkName` | string | `''` | | The name of the Managed Virtual Network | +| `publicNetworkAccess` | bool | `True` | | Enable or disable public network access. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the Azure Data Factory instance. | +| `resourceGroupName` | string | The name of the Resource Group with the Data factory. | +| `resourceId` | string | The Resource ID of the Data factory. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Factories](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories) +- [Factories/Integrationruntimes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/integrationRuntimes) +- [Factories/Managedvirtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DataFactory/2018-06-01/factories/managedVirtualNetworks) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.DataFactory/factories/version.json b/carml/1.0.1/Microsoft.DataFactory/factories/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DataFactory/factories/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/carml/1.0.1/Microsoft.Databricks/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Databricks/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..807fa7d63 --- /dev/null +++ b/carml/1.0.1/Microsoft.Databricks/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.Databricks/workspaces@2018-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: workspace +}] diff --git a/carml/1.0.1/Microsoft.Databricks/workspaces/.parameters/parameters.json b/carml/1.0.1/Microsoft.Databricks/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..7d3ba311e --- /dev/null +++ b/carml/1.0.1/Microsoft.Databricks/workspaces/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-adb-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Databricks/workspaces/deploy.bicep b/carml/1.0.1/Microsoft.Databricks/workspaces/deploy.bicep new file mode 100644 index 000000000..c71acd903 --- /dev/null +++ b/carml/1.0.1/Microsoft.Databricks/workspaces/deploy.bicep @@ -0,0 +1,161 @@ +@description('Required. The name of the Azure Databricks workspace to create') +param name string + +@description('Optional. The managed resource group ID') +param managedResourceGroupId string = '' + +@description('Optional. The pricing tier of workspace') +@allowed([ + 'trial' + 'standard' + 'premium' +]) +param pricingTier string = 'premium' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. The workspace\'s custom parameters.') +param workspaceParameters object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'dbfs' + 'clusters' + 'accounts' + 'jobs' + 'notebook' + 'ssh' + 'workspace' + 'secrets' + 'sqlPermissions' + 'instancePools' +]) +param diagnosticLogCategoriesToEnable array = [ + 'dbfs' + 'clusters' + 'accounts' + 'jobs' + 'notebook' + 'ssh' + 'workspace' + 'secrets' + 'sqlPermissions' + 'instancePools' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var managedResourceGroupName = '${name}-rg' +var managedResourceGroupId_var = '${subscription().id}/resourceGroups/${managedResourceGroupName}' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.Databricks/workspaces@2018-04-01' = { + name: name + location: location + tags: tags + sku: { + name: pricingTier + } + properties: { + managedResourceGroupId: (empty(managedResourceGroupId) ? managedResourceGroupId_var : managedResourceGroupId) + parameters: workspaceParameters + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +// Note: Diagnostic Settings are only supported by the premium tier +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if (pricingTier == 'premium' && ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName)))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DataBricks-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The name of the deployed databricks workspace') +output name string = workspace.name + +@description('The resource ID of the deployed databricks workspace') +output resourceId string = workspace.id + +@description('The resource group of the deployed databricks workspace') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Databricks/workspaces/readme.md b/carml/1.0.1/Microsoft.Databricks/workspaces/readme.md new file mode 100644 index 000000000..8fd1d8eca --- /dev/null +++ b/carml/1.0.1/Microsoft.Databricks/workspaces/readme.md @@ -0,0 +1,135 @@ +# Azure Databricks `[Microsoft.Databricks/workspaces]` + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Databricks/workspaces` | 2018-04-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Azure Databricks workspace to create | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[dbfs, clusters, accounts, jobs, notebook, ssh, workspace, secrets, sqlPermissions, instancePools]` | `[dbfs, clusters, accounts, jobs, notebook, ssh, workspace, secrets, sqlPermissions, instancePools]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managedResourceGroupId` | string | `''` | | The managed resource group ID | +| `pricingTier` | string | `'premium'` | `[trial, standard, premium]` | The pricing tier of workspace | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `workspaceParameters` | object | `{object}` | | The workspace's custom parameters. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `customPublicSubnetName` and `customPrivateSubnetName` + +- Require Network Security Groups attached to the subnets + - The rule don't have to be set, they are set through the deployment + +- The two subnets also need the delegation to service `Microsoft.Databricks/workspaces` + +### Parameter Usage: `workspaceParameters` + +- Include only those elements (e.g. amlWorkspaceId) as object if specified, otherwise remove it + +```json +"workspaceParameters": { + "value": { + "amlWorkspaceId": { + "value": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.MachineLearningServices/workspaces/xxx" + }, + "customVirtualNetworkId": { + "value": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx" + }, + "customPublicSubnetName": { + "value": "xxx" + }, + "customPrivateSubnetName": { + "value": "xxx" + }, + "enableNoPublicIp": { + "value": true + } + } + } +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed databricks workspace | +| `resourceGroupName` | string | The resource group of the deployed databricks workspace | +| `resourceId` | string | The resource ID of the deployed databricks workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Databricks/2018-04-01/workspaces) diff --git a/carml/1.0.1/Microsoft.Databricks/workspaces/version.json b/carml/1.0.1/Microsoft.Databricks/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Databricks/workspaces/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/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..1cb9dbf6f --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63') + 'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b') + 'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationgroups@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: appGroup +}] diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.parameters/min.parameters.json new file mode 100644 index 000000000..ecf7a145e --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.parameters/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": { + "name": { + "value": "<>-az-avdag-min-001" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "adp-<>-az-avdhp-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json new file mode 100644 index 000000000..2b43fed10 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdag-x-001" + }, + "location": { + "value": "westeurope" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "adp-<>-az-avdhp-x-001" + }, + "friendlyName": { + "value": "Remote Applications 1" + }, + "description": { + "value": "This is my first Remote Applications bundle" + }, + "applications": { + "value": [ + { + "name": "notepad", + "description": "Notepad by ARM template", + "friendlyName": "Notepad", + "filePath": "C:\\Windows\\System32\\notepad.exe", + "commandLineSetting": "DoNotAllow", + "commandLineArguments": "", + "showInPortal": true, + "iconPath": "C:\\Windows\\System32\\notepad.exe", + "iconIndex": 0 + }, + { + "name": "wordpad", + "filePath": "C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe", + "friendlyName": "Wordpad" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep new file mode 100644 index 000000000..d63d26667 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep @@ -0,0 +1,77 @@ +@sys.description('Required. Name of the Application Group to create the application(s) in.') +param appGroupName string + +@sys.description('Required. Name of the Application to be created in the Application Group.') +param name string + +@sys.description('Optional. Description of Application..') +param description string = '' + +@sys.description('Required. Friendly name of Application..') +param friendlyName string + +@sys.description('Required. Specifies a path for the executable file for the application.') +param filePath string + +@allowed([ + 'Allow' + 'DoNotAllow' + 'Require' +]) +@sys.description('Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all.') +param commandLineSetting string = 'DoNotAllow' + +@sys.description('Optional. Command-Line Arguments for Application.') +param commandLineArguments string = '' + +@sys.description('Optional. Specifies whether to show the RemoteApp program in the RD Web Access server.') +param showInPortal bool = false + +@sys.description('Optional. Path to icon.') +param iconPath string = '' + +@sys.description('Optional. Index of the icon.') +param iconIndex int = 0 + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource applicationGroup 'Microsoft.DesktopVirtualization/applicationGroups@2021-09-03-preview' existing = { + name: appGroupName +} + +resource application 'Microsoft.DesktopVirtualization/applicationGroups/applications@2021-07-12' = { + name: name + parent: applicationGroup + properties: { + description: description + friendlyName: friendlyName + filePath: filePath + commandLineSetting: commandLineSetting + commandLineArguments: commandLineArguments + showInPortal: showInPortal + iconPath: iconPath + iconIndex: iconIndex + } +} + +@sys.description('The resource ID of the deployed Application.') +output applicationResourceIds string = application.id + +@sys.description('The name of the Resource Group the AVD Application was created in.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The Name of the Application Group to register the Application in.') +output name string = appGroupName diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md new file mode 100644 index 000000000..87ea0b738 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md @@ -0,0 +1,50 @@ +# AVD Applications `[Microsoft.DesktopVirtualization/applicationGroups/applications]` + +This module deploys AVD Applications. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | 2021-07-12 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `appGroupName` | string | Name of the Application Group to create the application(s) in. | +| `filePath` | string | Specifies a path for the executable file for the application. | +| `friendlyName` | string | Friendly name of Application.. | +| `name` | string | Name of the Application to be created in the Application Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `commandLineArguments` | string | `''` | | Command-Line Arguments for Application. | +| `commandLineSetting` | string | `'DoNotAllow'` | `[Allow, DoNotAllow, Require]` | Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all. | +| `description` | string | `''` | | Description of Application.. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `iconIndex` | int | `0` | | Index of the icon. | +| `iconPath` | string | `''` | | Path to icon. | +| `showInPortal` | bool | `False` | | Specifies whether to show the RemoteApp program in the RD Web Access server. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationResourceIds` | string | The resource ID of the deployed Application. | +| `name` | string | The Name of the Application Group to register the Application in. | +| `resourceGroupName` | string | The name of the Resource Group the AVD Application was created in. | + +## Template references + +- [Applicationgroups/Applications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups/applications) diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/version.json b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/applications/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/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep new file mode 100644 index 000000000..6c8f84c09 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep @@ -0,0 +1,168 @@ +@sys.description('Required. Name of the Application Group to create this application in.') +@minLength(1) +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop') +@allowed([ + 'RemoteApp' + 'Desktop' +]) +param applicationGroupType string + +@sys.description('Required. Name of the Host Pool to be linked to this Application Group.') +param hostpoolName string + +@sys.description('Optional. The friendly name of the Application Group to be created.') +param friendlyName string = '' + +@sys.description('Optional. The description of the Application Group to be created.') +param description string = '' + +@sys.description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@sys.description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@sys.description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@sys.description('Optional. Resource ID of log analytics.') +param diagnosticWorkspaceId string = '' + +@sys.description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@sys.description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@sys.description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@sys.description('Optional. Tags of the resource.') +param tags object = {} + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' +] + +@sys.description('Optional. List of applications to be created in the Application Group.') +param applications array = [] + +@sys.description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource appGroup_hostpool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: hostpoolName +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationgroups@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + hostPoolArmPath: appGroup_hostpool.id + friendlyName: friendlyName + description: description + applicationGroupType: applicationGroupType + } +} + +resource appGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appGroup.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appGroup +} + +resource appGroup_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: appGroup +} + +module appGroup_applications 'applications/deploy.bicep' = [for (application, index) in applications: { + name: '${uniqueString(deployment().name, location)}-AppGroup-App-${index}' + params: { + name: application.name + appGroupName: appGroup.name + description: contains(application, 'description') ? application.description : '' + friendlyName: contains(application, 'friendlyName') ? application.friendlyName : appGroup.name + filePath: application.filePath + commandLineSetting: contains(application, 'commandLineSetting') ? application.commandLineSetting : 'DoNotAllow' + commandLineArguments: contains(application, 'commandLineArguments') ? application.commandLineArguments : '' + showInPortal: contains(application, 'showInPortal') ? application.showInPortal : false + iconPath: contains(application, 'iconPath') ? application.iconPath : application.filePath + iconIndex: contains(application, 'iconIndex') ? application.iconIndex : 0 + } +}] + +module appGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appGroup.id + } +}] + +@sys.description('The resource ID of the AVD application group') +output resourceId string = appGroup.id + +@sys.description('The resource group the AVD application group was deployed into') +output resourceGroupName string = resourceGroup().name + +@sys.description('The name of the AVD application group') +output name string = appGroup.name diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/readme.md b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/readme.md new file mode 100644 index 000000000..750713e79 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/readme.md @@ -0,0 +1,108 @@ +# AVD Application Groups `[Microsoft.DesktopVirtualization/applicationgroups]` + +This module deploys an Azure virtual desktop application group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/applicationGroups` | 2021-07-12 | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `applicationGroupType` | string | `[RemoteApp, Desktop]` | The type of the Application Group to be created. Allowed values: RemoteApp or Desktop | +| `hostpoolName` | string | | Name of the Host Pool to be linked to this Application Group. | +| `name` | string | | Name of the Application Group to create this application in. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `applications` | _[applications](applications/readme.md)_ array | `[]` | | List of applications to be created in the Application Group. | +| `description` | string | `''` | | The description of the Application Group to be created. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Checkpoint, Error, Management]` | `[Checkpoint, Error, Management]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of log analytics. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `friendlyName` | string | `''` | | The friendly name of the Application Group to be created. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD application group | +| `resourceGroupName` | string | The resource group the AVD application group was deployed into | +| `resourceId` | string | The resource ID of the AVD application group | + +## Template references + +- [Applicationgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups) +- [Applicationgroups/Applications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups/applications) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/version.json b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/applicationgroups/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/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..bc1b6b328 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Host Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc') + 'Desktop Virtualization Host Pool Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Session Host Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408') + 'Desktop Virtualization User Session Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(hostPool.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: hostPool +}] diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json new file mode 100644 index 000000000..ba8ef0e1f --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdhp-x-001" + }, + "location": { + "value": "westeurope" + }, + "hostpoolFriendlyName": { + "value": "AVDv2" + }, + "hostpoolDescription": { + "value": "My first AVD Host Pool" + }, + "hostpoolType": { + "value": "Pooled" + }, + "personalDesktopAssignmentType": { + "value": "Automatic" + }, + "maxSessionLimit": { + "value": 99999 + }, + "loadBalancerType": { + "value": "BreadthFirst" + }, + "customRdpProperty": { + "value": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;" + }, + "vmTemplate": { + "value": { + "domain": "domainname.onmicrosoft.com", + "galleryImageOffer": "office-365", + "galleryImagePublisher": "microsoftwindowsdesktop", + "galleryImageSKU": "20h1-evd-o365pp", + "imageType": "Gallery", + "imageUri": null, + "customImageId": null, + "namePrefix": "avdv2", + "osDiskType": "StandardSSD_LRS", + "useManagedDisks": true, + "vmSize": { + "id": "Standard_D2s_v3", + "cores": 2, + "ram": 8 + } + } + }, + "validationEnviroment": { + "value": false + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/deploy.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/deploy.bicep new file mode 100644 index 000000000..792a73db4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/deploy.bicep @@ -0,0 +1,214 @@ +@description('Required. Name of the Host Pool') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The friendly name of the Host Pool to be created.') +param hostpoolFriendlyName string = '' + +@description('Optional. The description of the Host Pool to be created.') +param hostpoolDescription string = '' + +@description('Optional. Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled.') +@allowed([ + 'Personal' + 'Pooled' +]) +param hostpoolType string = 'Pooled' + +@description('Optional. Set the type of assignment for a Personal Host Pool type') +@allowed([ + 'Automatic' + 'Direct' + '' +]) +param personalDesktopAssignmentType string = '' + +@description('Optional. Type of load balancer algorithm.') +@allowed([ + 'BreadthFirst' + 'DepthFirst' + 'Persistent' +]) +param loadBalancerType string = 'BreadthFirst' + +@description('Optional. Maximum number of sessions.') +param maxSessionLimit int = 99999 + +@description('Optional. Host Pool RDP properties') +param customRdpProperty string = 'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;' + +@description('Optional. Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation \'ring\' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment.') +param validationEnviroment bool = false + +@description('Optional. The necessary information for adding more VMs to this Host Pool.') +param vmTemplate object = {} + +@description('Optional. Host Pool token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the token will be valid for 8 hours.') +param tokenValidityLength string = 'PT8H' + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The type of preferred application group type, default to Desktop Application Group') +@allowed([ + 'Desktop' + 'None' + 'RailApplications' +]) +param preferredAppGroupType string = 'Desktop' + +@description('Optional. Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs.') +param startVMOnConnect bool = false + +@description('Optional. Validation host pool allows you to test service changes before they are deployed to production.') +param validationEnvironment bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' + 'Connection' + 'HostRegistration' + 'AgentHealthStatus' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' + 'Connection' + 'HostRegistration' + 'AgentHealthStatus' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var tokenExpirationTime = dateTimeAdd(baseTime, tokenValidityLength) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + friendlyName: hostpoolFriendlyName + description: hostpoolDescription + hostPoolType: hostpoolType + customRdpProperty: customRdpProperty + personalDesktopAssignmentType: any(personalDesktopAssignmentType) + preferredAppGroupType: preferredAppGroupType + maxSessionLimit: maxSessionLimit + loadBalancerType: loadBalancerType + validationEnviroment: validationEnviroment + startVMOnConnect: startVMOnConnect + validationEnvironment: validationEnvironment + registrationInfo: { + expirationTime: tokenExpirationTime + token: null + registrationTokenOperation: 'Update' + } + vmTemplate: ((!empty(vmTemplate)) ? null : string(vmTemplate)) + } +} + +resource hostPool_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${hostPool.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: hostPool +} + +resource hostPool_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: hostPool +} + +module hostPool_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-HostPool-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: hostPool.id + } +}] + +@description('The resource ID of the AVD host pool') +output resourceId string = hostPool.id + +@description('The resource group the AVD host pool was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD host pool') +output name string = hostPool.name + +@description('The expiration time for the registration token') +output tokenExpirationTime string = dateTimeAdd(baseTime, tokenValidityLength) diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/readme.md b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/readme.md new file mode 100644 index 000000000..455d6783d --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/readme.md @@ -0,0 +1,154 @@ +# AVD Host Pools `[Microsoft.DesktopVirtualization/hostpools]` + +This module deploys an Azure virtual desktop host pool. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/hostPools` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Host Pool | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `customRdpProperty` | string | `'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;'` | | Host Pool RDP properties | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Checkpoint, Error, Management, Connection, HostRegistration, AgentHealthStatus]` | `[Checkpoint, Error, Management, Connection, HostRegistration, AgentHealthStatus]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hostpoolDescription` | string | `''` | | The description of the Host Pool to be created. | +| `hostpoolFriendlyName` | string | `''` | | The friendly name of the Host Pool to be created. | +| `hostpoolType` | string | `'Pooled'` | `[Personal, Pooled]` | Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled. | +| `loadBalancerType` | string | `'BreadthFirst'` | `[BreadthFirst, DepthFirst, Persistent]` | Type of load balancer algorithm. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxSessionLimit` | int | `99999` | | Maximum number of sessions. | +| `personalDesktopAssignmentType` | string | `''` | `[Automatic, Direct, ]` | Set the type of assignment for a Personal Host Pool type | +| `preferredAppGroupType` | string | `'Desktop'` | `[Desktop, None, RailApplications]` | The type of preferred application group type, default to Desktop Application Group | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `startVMOnConnect` | bool | `False` | | Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `tokenValidityLength` | string | `'PT8H'` | | Host Pool token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the token will be valid for 8 hours. | +| `validationEnviroment` | bool | `False` | | Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation 'ring' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment. | +| `validationEnvironment` | bool | `False` | | Validation host pool allows you to test service changes before they are deployed to production. | +| `vmTemplate` | object | `{object}` | | The necessary information for adding more VMs to this Host Pool. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `vmTemplate` + +The below parameter object is converted to an in-line string when handed over to the resource deployment, since that only takes strings. + +```json +"vmTemplate": { + "value": { + "domain": ".com", + "galleryImageOffer": "office-365", + "galleryImagePublisher": "microsoftwindowsdesktop", + "galleryImageSKU": "19h2-evd-o365pp", + "imageType": "Gallery", + "imageUri": null, + "customImageId": null, + "namePrefix": "AVDv2", + "osDiskType": "StandardSSD_LRS", + "useManagedDisks": true, + "vmSize": { + "id": "Standard_D2s_v3", + "cores": 2, + "ram": 8 + } + } +} +``` + +### Parameter Usage: `customRdpProperty` + +```json +"customRdpProperty": { + "value": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode ID:i:2;" +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD host pool | +| `resourceGroupName` | string | The resource group the AVD host pool was deployed into | +| `resourceId` | string | The resource ID of the AVD host pool | +| `tokenExpirationTime` | string | The expiration time for the registration token | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Hostpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/hostPools) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/version.json b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/hostpools/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/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..bc1b6b328 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Host Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc') + 'Desktop Virtualization Host Pool Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Session Host Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408') + 'Desktop Virtualization User Session Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(hostPool.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: hostPool +}] diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/.parameters/min.parameters.json new file mode 100644 index 000000000..e576bf370 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdsp-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/deploy.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/deploy.bicep new file mode 100644 index 000000000..3c6a161df --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/deploy.bicep @@ -0,0 +1,156 @@ +@description('Required. Name of the scaling plan') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Friendly Name of the scaling plan') +param friendlyName string = name + +@description('Optional. Description of the scaling plan.') +param scalingplanDescription string = name + +@description('Optional. Timezone to be used for the scaling plan.') +param timeZone string = 'W. Europe Standard Time' + +@allowed([ + 'Pooled' +]) +@description('Optional. The type of hostpool where this scaling plan should be applied.') +param hostPoolType string = 'Pooled' + +@description('Optional. Provide a tag to be used for hosts that should not be affected by the scaling plan.') +param exclusionTag string = '' + +@description('Optional. The schedules related to this scaling plan. If no value is provided a default schedule will be provided.') +param schedules array = [ + { + rampUpStartTime: { + hour: 7 + minute: 0 + } + peakStartTime: { + hour: 9 + minute: 0 + } + rampDownStartTime: { + hour: 18 + minute: 0 + } + offPeakStartTime: { + hour: 20 + minute: 0 + } + name: 'weekdays_schedule' + daysOfWeek: [ + 'Monday' + 'Tuesday' + 'Wednesday' + 'Thursday' + 'Friday' + ] + rampUpLoadBalancingAlgorithm: 'DepthFirst' + rampUpMinimumHostsPct: 20 + rampUpCapacityThresholdPct: 60 + peakLoadBalancingAlgorithm: 'DepthFirst' + rampDownLoadBalancingAlgorithm: 'DepthFirst' + rampDownMinimumHostsPct: 10 + rampDownCapacityThresholdPct: 90 + rampDownForceLogoffUsers: true + rampDownWaitTimeMinutes: 30 + rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' + rampDownStopHostsWhen: 'ZeroSessions' + offPeakLoadBalancingAlgorithm: 'DepthFirst' + } +] + +@description('Optional. An array of references to hostpools.') +param hostPoolReferences array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Autoscale' +]) +param logsToEnable array = [ + 'Autoscale' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource scalingPlan 'Microsoft.DesktopVirtualization/scalingPlans@2021-09-03-preview' = { + name: name + location: location + tags: tags + properties: { + friendlyName: friendlyName + timeZone: timeZone + hostPoolType: hostPoolType + exclusionTag: exclusionTag + schedules: schedules + hostPoolReferences: hostPoolReferences + description: scalingplanDescription + } +} + +resource scalingplan_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${scalingPlan.name}-diagnosticsetting' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: scalingPlan +} + +module scalingplan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Workspace-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: scalingPlan.id + } +}] + +@description('The resource ID of the AVD scaling plan') +output resourceId string = scalingPlan.id + +@description('The resource group the AVD scaling plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD scaling plan') +output name string = scalingPlan.name diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/readme.md b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/readme.md new file mode 100644 index 000000000..9bbb255d1 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/readme.md @@ -0,0 +1,151 @@ +# AVD Scaling Plans `[Microsoft.DesktopVirtualization/scalingPlans]` + +This module deploys an AVD Scaling Plan. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/scalingPlans` | 2021-09-03-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the scaling plan | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `exclusionTag` | string | `''` | | Provide a tag to be used for hosts that should not be affected by the scaling plan. | +| `friendlyName` | string | `[parameters('name')]` | | Friendly Name of the scaling plan | +| `hostPoolReferences` | array | `[]` | | An array of references to hostpools. | +| `hostPoolType` | string | `'Pooled'` | `[Pooled]` | The type of hostpool where this scaling plan should be applied. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `logsToEnable` | array | `[Autoscale]` | `[Autoscale]` | The name of logs that will be streamed. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scalingplanDescription` | string | `[parameters('name')]` | | Description of the scaling plan. | +| `schedules` | array | `[System.Collections.Hashtable]` | | The schedules related to this scaling plan. If no value is provided a default schedule will be provided. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `'W. Europe Standard Time'` | | Timezone to be used for the scaling plan. | + + +### Parameter Usage: `schedules` + +Multiple schedules can be provided as needed. If a schedule is not provided, a default schedule will be created. + +```json +"schedules" : { + "value": [ + { + "rampUpStartTime": { + "hour": 7, + "minute": 0 + }, + "peakStartTime": { + "hour": 9, + "minute": 0 + }, + "rampDownStartTime": { + "hour": 18, + "minute": 0 + }, + "offPeakStartTime": { + "hour": 20, + "minute": 0 + }, + "name": "weekdays_schedule", + "daysOfWeek": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday" + ], + "rampUpLoadBalancingAlgorithm": "DepthFirst", + "rampUpMinimumHostsPct": 20, + "rampUpCapacityThresholdPct": 60, + "peakLoadBalancingAlgorithm": "DepthFirst", + "rampDownLoadBalancingAlgorithm": "DepthFirst", + "rampDownMinimumHostsPct": 10, + "rampDownCapacityThresholdPct": 90, + "rampDownForceLogoffUsers": true, + "rampDownWaitTimeMinutes": 30, + "rampDownNotificationMessage": "You will be logged off in 30 min. Make sure to save your work.", + "rampDownStopHostsWhen": "ZeroSessions", + "offPeakLoadBalancingAlgorithm": "DepthFirst" + }] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD scaling plan | +| `resourceGroupName` | string | The resource group the AVD scaling plan was deployed into | +| `resourceId` | string | The resource ID of the AVD scaling plan | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Scalingplans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-09-03-preview/scalingPlans) diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/version.json b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/version.json new file mode 100644 index 000000000..cfda93cb0 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/scalingplans/version.json @@ -0,0 +1,3 @@ +{ + "version": "0.4" +} \ No newline at end of file diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c51449b59 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,58 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b') + 'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.DesktopVirtualization/workspaces@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: workspace +}] diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..7220e4d78 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdws-x-001" + }, + "location": { + "value": "westeurope" + }, + "appGroupResourceIds": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.DesktopVirtualization/applicationgroups/adp-<>-az-avdag-x-001" + ] + }, + "workspaceFriendlyName": { + "value": "My first AVD Workspace" + }, + "workspaceDescription": { + "value": "This is my first AVD Workspace" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/deploy.bicep b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/deploy.bicep new file mode 100644 index 000000000..9d6f2c121 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/deploy.bicep @@ -0,0 +1,138 @@ +@description('Required. The name of the workspace to be attach to new Application Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Resource IDs fo the existing Application groups this workspace will group together.') +param appGroupResourceIds array = [] + +@description('Optional. The friendly name of the Workspace to be created.') +param workspaceFriendlyName string = '' + +@description('Optional. The description of the Workspace to be created.') +param workspaceDescription string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' + 'Feed' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' + 'Feed' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.DesktopVirtualization/workspaces@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + applicationGroupReferences: appGroupResourceIds + description: workspaceDescription + friendlyName: workspaceFriendlyName + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Workspace-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The resource ID of the AVD workspace') +output resourceId string = workspace.id + +@description('The resource group the AVD workspace was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD workspace') +output name string = workspace.name diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/readme.md b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/readme.md new file mode 100644 index 000000000..e3285fd88 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/readme.md @@ -0,0 +1,104 @@ +# AVD Workspaces `[Microsoft.DesktopVirtualization/workspaces]` + +This module deploys an Azure virtual desktop workspace. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/workspaces` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `appGroupResourceIds` | array | Resource IDs fo the existing Application groups this workspace will group together. | +| `name` | string | The name of the workspace to be attach to new Application Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Checkpoint, Error, Management, Feed]` | `[Checkpoint, Error, Management, Feed]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `workspaceDescription` | string | `''` | | The description of the Workspace to be created. | +| `workspaceFriendlyName` | string | `''` | | The friendly name of the Workspace to be created. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD workspace | +| `resourceGroupName` | string | The resource group the AVD workspace was deployed into | +| `resourceId` | string | The resource ID of the AVD workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/workspaces) diff --git a/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/version.json b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DesktopVirtualization/workspaces/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/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b641b84ba --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Cosmos DB Account Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'CosmosBackupOperator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-06-15' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(databaseAccount.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: databaseAccount +}] diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/mongodb.parameters.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/mongodb.parameters.json new file mode 100644 index 000000000..c9c6465b3 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/mongodb.parameters.json @@ -0,0 +1,240 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cdb-mongodb-001" + }, + "location": { + "value": "West Europe" + }, + "locations": { + "value": [ + { + "locationName": "West Europe", + "failoverPriority": 0, + "isZoneRedundant": false + }, + { + "locationName": "North Europe", + "failoverPriority": 1, + "isZoneRedundant": false + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "mongodbDatabases": { + "value": [ + { + "name": "<>-az-mdb-x-001", + "collections": [ + { + "name": "car_collection", + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "car_id", + "car_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "shardKey": { + "car_id": "Hash" + } + }, + { + "name": "truck_collection", + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "truck_id", + "truck_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "shardKey": { + "truck_id": "Hash" + } + } + ] + }, + { + "name": "<>-az-mdb-x-002", + "collections": [ + { + "name": "bike_collection", + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "bike_id", + "bike_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "shardKey": { + "bike_id": "Hash" + } + }, + { + "name": "bicycle_collection", + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "bicycle_id", + "bicycle_model" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ], + "shardKey": { + "bicycle_id": "Hash" + } + } + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/plain.parameters.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/plain.parameters.json new file mode 100644 index 000000000..70fbc40cc --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/plain.parameters.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cdb-plain-001" + }, + "locations": { + "value": [ + { + "locationName": "West Europe", + "failoverPriority": 0, + "isZoneRedundant": false + }, + { + "locationName": "North Europe", + "failoverPriority": 1, + "isZoneRedundant": false + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/sqldb.parameters.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/sqldb.parameters.json new file mode 100644 index 000000000..11f83861d --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/.parameters/sqldb.parameters.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cdb-sqldb-001" + }, + "location": { + "value": "West Europe" + }, + "locations": { + "value": [ + { + "locationName": "West Europe", + "failoverPriority": 0, + "isZoneRedundant": false + }, + { + "locationName": "North Europe", + "failoverPriority": 1, + "isZoneRedundant": false + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "sqlDatabases": { + "value": [ + { + "name": "<>-az-sql-x-001", + "containers": [ + { + "name": "container-001", + "paths": [ + "/myPartitionKey" + ], + "kind": "Hash" + } + ] + }, + { + "name": "<>-az-sql-x-002", + "containers": [] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/deploy.bicep b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/deploy.bicep new file mode 100644 index 000000000..ac0417742 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/deploy.bicep @@ -0,0 +1,280 @@ +@description('Required. Name of the Database Account') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Database Account resource.') +param tags object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The offer type for the Cosmos DB database account.') +@allowed([ + 'Standard' +]) +param databaseAccountOfferType string = 'Standard' + +@description('Required. Locations enabled for the Cosmos DB account.') +param locations array + +@allowed([ + 'Eventual' + 'ConsistentPrefix' + 'Session' + 'BoundedStaleness' + 'Strong' +]) +@description('Optional. The default consistency level of the Cosmos DB account.') +param defaultConsistencyLevel string = 'Session' + +@description('Optional. Enable automatic failover for regions') +param automaticFailover bool = true + +@minValue(10) +@maxValue(2147483647) +@description('Optional. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000.') +param maxStalenessPrefix int = 100000 + +@minValue(5) +@maxValue(86400) +@description('Optional. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400.') +param maxIntervalInSeconds int = 300 + +@description('Optional. Specifies the MongoDB server version to use.') +@allowed([ + '3.2' + '3.6' + '4.0' +]) +param serverVersion string = '4.0' + +@description('Optional. SQL Databases configurations') +param sqlDatabases array = [] + +@description('Optional. MongoDB Databases configurations') +param mongodbDatabases array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DataPlaneRequests' + 'MongoRequests' + 'QueryRuntimeStatistics' + 'PartitionKeyStatistics' + 'PartitionKeyRUConsumption' + 'ControlPlaneRequests' + 'CassandraRequests' + 'GremlinRequests' + 'TableApiRequests' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DataPlaneRequests' + 'MongoRequests' + 'QueryRuntimeStatistics' + 'PartitionKeyStatistics' + 'PartitionKeyRUConsumption' + 'ControlPlaneRequests' + 'CassandraRequests' + 'GremlinRequests' + 'TableApiRequests' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Requests' +]) +param diagnosticMetricsToEnable array = [ + 'Requests' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +var consistencyPolicy = { + Eventual: { + defaultConsistencyLevel: 'Eventual' + } + ConsistentPrefix: { + defaultConsistencyLevel: 'ConsistentPrefix' + } + Session: { + defaultConsistencyLevel: 'Session' + } + BoundedStaleness: { + defaultConsistencyLevel: 'BoundedStaleness' + maxStalenessPrefix: maxStalenessPrefix + maxIntervalInSeconds: maxIntervalInSeconds + } + Strong: { + defaultConsistencyLevel: 'Strong' + } +} + +var databaseAccount_locations = [for location in locations: { + failoverPriority: location.failoverPriority + isZoneRedundant: location.isZoneRedundant + locationName: location.locationName +}] + +var kind = !empty(sqlDatabases) ? 'GlobalDocumentDB' : (!empty(mongodbDatabases) ? 'MongoDB' : 'Parse') + +var databaseAccount_properties = !empty(sqlDatabases) ? { + consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] + locations: databaseAccount_locations + databaseAccountOfferType: databaseAccountOfferType + enableAutomaticFailover: automaticFailover +} : (!empty(mongodbDatabases) ? { + consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] + locations: databaseAccount_locations + databaseAccountOfferType: databaseAccountOfferType + apiProperties: { + serverVersion: serverVersion + } +} : { + databaseAccountOfferType: databaseAccountOfferType +}) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-06-15' = { + name: name + location: location + tags: tags + identity: identity + kind: kind + properties: databaseAccount_properties +} + +resource databaseAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${databaseAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: databaseAccount +} + +resource databaseAccount_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: databaseAccount +} + +module databaseAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: databaseAccount.id + } +}] + +module sqlDatabases_resource 'sqlDatabases/deploy.bicep' = [for sqlDatabase in sqlDatabases: { + name: '${uniqueString(deployment().name, location)}-sqldb-${sqlDatabase.name}' + params: { + databaseAccountName: databaseAccount.name + name: sqlDatabase.name + containers: contains(sqlDatabase, 'containers') ? sqlDatabase.containers : [] + } +}] + +module mongodbDatabases_resource 'mongodbDatabases/deploy.bicep' = [for mongodbDatabase in mongodbDatabases: { + name: '${uniqueString(deployment().name, location)}-mongodb-${mongodbDatabase.name}' + params: { + databaseAccountName: databaseAccount.name + name: mongodbDatabase.name + collections: contains(mongodbDatabase, 'collections') ? mongodbDatabase.collections : [] + } +}] + +@description('The name of the database account.') +output name string = databaseAccount.name + +@description('The resource ID of the database account.') +output resourceId string = databaseAccount.id + +@description('The name of the resource group the database account was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(databaseAccount.identity, 'principalId') ? databaseAccount.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/deploy.bicep b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/deploy.bicep new file mode 100644 index 000000000..77283b909 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/deploy.bicep @@ -0,0 +1,64 @@ +@description('Required. Name of the Cosmos DB database account.') +param databaseAccountName string + +@description('Required. Name of the mongodb database') +param mongodbDatabaseName string + +@description('Required. Name of the collection') +param name string + +@description('Optional. Name of the mongodb database') +param throughput int = 400 + +@description('Required. Indexes for the collection') +param indexes array + +@description('Required. ShardKey for the collection') +param shardKey object + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName + + resource mongodbDatabase 'mongodbDatabases@2021-07-01-preview' existing = { + name: mongodbDatabaseName + } +} + +resource collection 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections@2021-07-01-preview' = { + name: name + parent: databaseAccount::mongodbDatabase + properties: { + options: { + throughput: throughput + } + resource: { + id: name + indexes: indexes + shardKey: shardKey + } + } +} + +@description('The name of the mongodb database.') +output name string = collection.name + +@description('The resource ID of the mongodb database.') +output resourceId string = collection.id + +@description('The name of the resource group the mongodb database was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/readme.md b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/readme.md new file mode 100644 index 000000000..f5e039262 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/readme.md @@ -0,0 +1,104 @@ +# DocumentDB Database Account MongoDB databases Collections `[Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections]` + +This module deploys a collection within a MongoDB. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections` | 2021-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `databaseAccountName` | string | Name of the Cosmos DB database account. | +| `indexes` | array | Indexes for the collection | +| `mongodbDatabaseName` | string | Name of the mongodb database | +| `name` | string | Name of the collection | +| `shardKey` | object | ShardKey for the collection | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `throughput` | int | `400` | Name of the mongodb database | + + +### Parameter Usage: `indexes` + +Array of index keys as MongoIndex. The array contains keys for each MongoDB collection in the Azure Cosmos DB service with a collection resource object (as `key`) and collection index options (as `options`). + +```json + "indexes": { + "value": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + }, + { + "key": { + "keys": [ + "estate_id", + "estate_address" + ] + }, + "options": { + "unique": true + } + }, + { + "key": { + "keys": [ + "_ts" + ] + }, + "options": { + "expireAfterSeconds": 2629746 + } + } + ] + } +``` + +### Parameter Usage: `shardKey` + +The shard key and partition kind pair, only support "Hash" partition kind. + +```json + "shardKey": { + "value": { + "estate_id": "Hash" + } + } +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the mongodb database. | +| `resourceGroupName` | string | The name of the resource group the mongodb database was created in. | +| `resourceId` | string | The resource ID of the mongodb database. | + +## Template references + +- [Databaseaccounts/Mongodbdatabases/Collections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases/collections) diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/version.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/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/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/deploy.bicep b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/deploy.bicep new file mode 100644 index 000000000..fed49e6bc --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/deploy.bicep @@ -0,0 +1,67 @@ +@description('Required. Name of the Cosmos DB database account.') +param databaseAccountName string + +@description('Required. Name of the mongodb database') +param name string + +@description('Optional. Name of the mongodb database') +param throughput int = 400 + +@description('Optional. Collections in the mongodb database') +param collections array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName +} + +resource mongodbDatabase 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases@2021-07-01-preview' = { + name: name + parent: databaseAccount + tags: tags + properties: { + resource: { + id: name + } + options: { + throughput: throughput + } + } +} + +module mongodbDatabase_collections 'collections/deploy.bicep' = [for collection in collections: { + name: '${uniqueString(deployment().name, mongodbDatabase.name)}-collection-${collection.name}' + params: { + databaseAccountName: databaseAccountName + mongodbDatabaseName: name + name: collection.name + indexes: collection.indexes + shardKey: collection.shardKey + } +}] + +@description('The name of the mongodb database.') +output name string = mongodbDatabase.name + +@description('The resource ID of the mongodb database.') +output resourceId string = mongodbDatabase.id + +@description('The name of the resource group the mongodb database was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/readme.md b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/readme.md new file mode 100644 index 000000000..9b43c779d --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/readme.md @@ -0,0 +1,68 @@ +# DocumentDB Database Account MongoDB databases `[Microsoft.DocumentDB/databaseAccounts/mongodbDatabases]` + +This module deploys a MongoDB within a CosmosDB account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases` | 2021-07-01-preview | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections` | 2021-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `databaseAccountName` | string | Name of the Cosmos DB database account. | +| `name` | string | Name of the mongodb database | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `collections` | _[collections](collections/readme.md)_ array | `[]` | Collections in the mongodb database | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `tags` | object | `{object}` | Tags of the resource. | +| `throughput` | int | `400` | Name of the mongodb database | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `collections` + +Please reference the documentation for [collections](./collections/readme.md) + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the mongodb database. | +| `resourceGroupName` | string | The name of the resource group the mongodb database was created in. | +| `resourceId` | string | The resource ID of the mongodb database. | + +## Template references + +- [Databaseaccounts/Mongodbdatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases) +- [Databaseaccounts/Mongodbdatabases/Collections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases/collections) diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/version.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/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/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/readme.md b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/readme.md new file mode 100644 index 000000000..5a4f48de9 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/readme.md @@ -0,0 +1,241 @@ +# DocumentDB Database Accounts `[Microsoft.DocumentDB/databaseAccounts]` + +This module deploys a DocumentDB database account and its child resources. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DocumentDB/databaseAccounts` | 2021-06-15 | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases` | 2021-07-01-preview | +| `Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections` | 2021-07-01-preview | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases` | 2021-06-15 | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | 2021-07-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `locations` | array | Locations enabled for the Cosmos DB account. | +| `name` | string | Name of the Database Account | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automaticFailover` | bool | `True` | | Enable automatic failover for regions | +| `databaseAccountOfferType` | string | `'Standard'` | `[Standard]` | The offer type for the Cosmos DB database account. | +| `defaultConsistencyLevel` | string | `'Session'` | `[Eventual, ConsistentPrefix, Session, BoundedStaleness, Strong]` | The default consistency level of the Cosmos DB account. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DataPlaneRequests, MongoRequests, QueryRuntimeStatistics, PartitionKeyStatistics, PartitionKeyRUConsumption, ControlPlaneRequests, CassandraRequests, GremlinRequests, TableApiRequests]` | `[DataPlaneRequests, MongoRequests, QueryRuntimeStatistics, PartitionKeyStatistics, PartitionKeyRUConsumption, ControlPlaneRequests, CassandraRequests, GremlinRequests, TableApiRequests]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Requests]` | `[Requests]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxIntervalInSeconds` | int | `300` | | Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400. | +| `maxStalenessPrefix` | int | `100000` | | Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000. | +| `mongodbDatabases` | _[mongodbDatabases](mongodbDatabases/readme.md)_ array | `[]` | | MongoDB Databases configurations | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serverVersion` | string | `'4.0'` | `[3.2, 3.6, 4.0]` | Specifies the MongoDB server version to use. | +| `sqlDatabases` | _[sqlDatabases](sqlDatabases/readme.md)_ array | `[]` | | SQL Databases configurations | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the Database Account resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `locations` + +```json +"locations": { + "value": [ + { + "failoverPriority": 1, + "locationName": "East US", + "isZoneRedundant": false + } + ] +} +``` + +### Parameter Usage: `sqlDatabases` + +```json +"sqlDatabases": { + "value": [ + { + "name": "sxx-az-sql-x-001", + "containers": [ + "container-001", + "container-002" + ] + }, + { + "name": "sxx-az-sql-x-002", + "containers": [] + } + ] +} +``` + +### Parameter Usage: `mongodbDatabases` + +```json +"mongodbDatabases": { + "value": [ + { + "name": "sxx-az-mdb-x-001", + "collections": [ + <...> + ] + }, + { + "name": "sxx-az-mdb-x-002", + "collections": [ + <...> + ] + } + ] +} +``` + +Please reference the documentation for [mongodbDatabases](./mongodbDatabases/readme.md) + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to 'ServicePrincipal'. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Desktop Virtualization User", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the database account. | +| `resourceGroupName` | string | The name of the resource group the database account was created in. | +| `resourceId` | string | The resource ID of the database account. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Databaseaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-06-15/databaseAccounts) +- [Databaseaccounts/Mongodbdatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases) +- [Databaseaccounts/Mongodbdatabases/Collections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/mongodbDatabases/collections) +- [Databaseaccounts/Sqldatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-06-15/databaseAccounts/sqlDatabases) +- [Databaseaccounts/Sqldatabases/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/sqlDatabases/containers) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/deploy.bicep b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/deploy.bicep new file mode 100644 index 000000000..e2b05d0f1 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/deploy.bicep @@ -0,0 +1,75 @@ +@description('Required. Name of the Database Account') +param databaseAccountName string + +@description('Required. Name of the SQL Database ') +param sqlDatabaseName string + +@description('Required. Name of the container.') +param name string + +@description('Optional. Request Units per second') +param throughput int = 400 + +@description('Optional. Tags of the SQL Database resource.') +param tags object = {} + +@description('Optional. List of paths using which data within the container can be partitioned') +param paths array = [] + +@description('Optional. Indicates the kind of algorithm used for partitioning') +@allowed([ + 'Hash' + 'MultiHash' + 'Range' +]) +param kind string = 'Hash' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName + + resource sqlDatabase 'sqlDatabases@2021-07-01-preview' existing = { + name: sqlDatabaseName + } +} + +resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2021-07-01-preview' = { + name: name + parent: databaseAccount::sqlDatabase + tags: tags + properties: { + resource: { + id: name + partitionKey: { + paths: paths + kind: kind + } + } + options: { + throughput: throughput + } + } +} + +@description('The name of the container.') +output name string = container.name + +@description('The resource ID of the container.') +output resourceId string = container.id + +@description('The name of the resource group the container was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readme.md b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readme.md new file mode 100644 index 000000000..9ea90228a --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readme.md @@ -0,0 +1,62 @@ +# DocumentDB Database Account SQL Databases Containers `[Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers]` + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | 2021-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `databaseAccountName` | string | Name of the Database Account | +| `name` | string | Name of the container. | +| `sqlDatabaseName` | string | Name of the SQL Database | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `kind` | string | `'Hash'` | `[Hash, MultiHash, Range]` | Indicates the kind of algorithm used for partitioning | +| `paths` | array | `[]` | | List of paths using which data within the container can be partitioned | +| `tags` | object | `{object}` | | Tags of the SQL Database resource. | +| `throughput` | int | `400` | | Request Units per second | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the container. | +| `resourceGroupName` | string | The name of the resource group the container was created in. | +| `resourceId` | string | The resource ID of the container. | + +## Template references + +- [Databaseaccounts/Sqldatabases/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/sqlDatabases/containers) diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/version.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/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/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/deploy.bicep b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/deploy.bicep new file mode 100644 index 000000000..29d0eb212 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/deploy.bicep @@ -0,0 +1,67 @@ +@description('Required. ID of the Cosmos DB database account.') +param databaseAccountName string + +@description('Required. Name of the SQL database ') +param name string + +@description('Optional. Array of containers to deploy in the SQL database.') +param containers array = [] + +@description('Optional. Request units per second') +param throughput int = 400 + +@description('Optional. Tags of the SQL database resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2021-07-01-preview' existing = { + name: databaseAccountName +} + +resource sqlDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2021-06-15' = { + name: name + parent: databaseAccount + tags: tags + properties: { + resource: { + id: name + } + options: { + throughput: throughput + } + } +} + +module container 'containers/deploy.bicep' = [for container in containers: { + name: '${uniqueString(deployment().name, sqlDatabase.name)}-sqldb-${container.name}' + params: { + databaseAccountName: databaseAccountName + sqlDatabaseName: name + name: container.name + paths: container.paths + kind: container.kind + } +}] + +@description('The name of the SQL database.') +output name string = sqlDatabase.name + +@description('The resource ID of the SQL database.') +output resourceId string = sqlDatabase.id + +@description('The name of the resource group the SQL database was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/readme.md b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/readme.md new file mode 100644 index 000000000..d7821d482 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/readme.md @@ -0,0 +1,62 @@ +# DocumentDB Database Account SQL Databases `[Microsoft.DocumentDB/databaseAccounts/sqlDatabases]` + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases` | 2021-06-15 | +| `Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers` | 2021-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `databaseAccountName` | string | ID of the Cosmos DB database account. | +| `name` | string | Name of the SQL database | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `containers` | _[containers](containers/readme.md)_ array | `[]` | Array of containers to deploy in the SQL database. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `tags` | object | `{object}` | Tags of the SQL database resource. | +| `throughput` | int | `400` | Request units per second | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SQL database. | +| `resourceGroupName` | string | The name of the resource group the SQL database was created in. | +| `resourceId` | string | The resource ID of the SQL database. | + +## Template references + +- [Databaseaccounts/Sqldatabases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-06-15/databaseAccounts/sqlDatabases) +- [Databaseaccounts/Sqldatabases/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DocumentDB/2021-07-01-preview/databaseAccounts/sqlDatabases/containers) diff --git a/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/version.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/sqlDatabases/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/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/version.json b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.DocumentDB/databaseAccounts/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/carml/1.0.1/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..82ab478cd --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.1/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..280920613 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(systemTopic.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: systemTopic +}] diff --git a/carml/1.0.1/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json new file mode 100644 index 000000000..87be2f37f --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.parameters/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": { + "name": { + "value": "<>-az-egstn-x-002" + }, + "source": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "topicType": { + "value": "Microsoft.Storage.StorageAccounts" + } + } +} diff --git a/carml/1.0.1/Microsoft.EventGrid/systemTopics/.parameters/parameters.json b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.parameters/parameters.json new file mode 100644 index 000000000..46728a692 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-egstn-x-001" + }, + "source": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "topicType": { + "value": "Microsoft.Storage.StorageAccounts" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.EventGrid/systemTopics/deploy.bicep b/carml/1.0.1/Microsoft.EventGrid/systemTopics/deploy.bicep new file mode 100644 index 000000000..ce60faf00 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/deploy.bicep @@ -0,0 +1,177 @@ +@description('Required. The name of the Event Grid Topic') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Required. Source for the system topic.') +param source string + +@description('Required. TopicType for the system topic.') +param topicType string + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DeliveryFailures' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DeliveryFailures' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' = { + name: name + location: location + identity: identity + tags: tags + properties: { + source: source + topicType: topicType + } +} + +resource systemTopic_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${systemTopic.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: systemTopic +} + +resource systemTopic_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: systemTopic +} + +module systemTopic_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-EventGrid-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: systemTopic.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module systemTopic_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EventGrid-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: systemTopic.id + } +}] + +@description('The name of the event grid system topic') +output name string = systemTopic.name + +@description('The resource ID of the event grid system topic') +output resourceId string = systemTopic.id + +@description('The name of the resource group the event grid system topic was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(systemTopic.identity, 'principalId') ? systemTopic.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.EventGrid/systemTopics/readme.md b/carml/1.0.1/Microsoft.EventGrid/systemTopics/readme.md new file mode 100644 index 000000000..f73d7f5c6 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/readme.md @@ -0,0 +1,161 @@ +# Event Grid System Topics `[Microsoft.EventGrid/systemTopics]` + +This module deploys an Event Grid System Topic. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventGrid/systemTopics` | 2021-12-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Event Grid Topic | +| `source` | string | Source for the system topic. | +| `topicType` | string | TopicType for the system topic. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DeliveryFailures]` | `[DeliveryFailures]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the event grid system topic | +| `resourceGroupName` | string | The name of the resource group the event grid system topic was deployed into | +| `resourceId` | string | The resource ID of the event grid system topic | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Systemtopics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2021-12-01/systemTopics) diff --git a/carml/1.0.1/Microsoft.EventGrid/systemTopics/version.json b/carml/1.0.1/Microsoft.EventGrid/systemTopics/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/systemTopics/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/carml/1.0.1/Microsoft.EventGrid/topics/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.EventGrid/topics/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..82ab478cd --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/topics/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.1/Microsoft.EventGrid/topics/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.EventGrid/topics/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..179c5a117 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/topics/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource eventGrid 'Microsoft.EventGrid/topics@2020-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(eventGrid.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: eventGrid +}] diff --git a/carml/1.0.1/Microsoft.EventGrid/topics/.parameters/parameters.json b/carml/1.0.1/Microsoft.EventGrid/topics/.parameters/parameters.json new file mode 100644 index 000000000..6a793c3a9 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/topics/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-egtn-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.EventGrid/topics/deploy.bicep b/carml/1.0.1/Microsoft.EventGrid/topics/deploy.bicep new file mode 100644 index 000000000..516839abb --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/topics/deploy.bicep @@ -0,0 +1,162 @@ +@description('Required. The name of the Event Grid Topic') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Determines if traffic is allowed over public network.') +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Array of IPs to whitelist.') +param inboundIpRules array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DeliveryFailures' + 'PublishFailures' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DeliveryFailures' + 'PublishFailures' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource eventGrid 'Microsoft.EventGrid/topics@2020-06-01' = { + name: name + location: location + tags: tags + properties: { + publicNetworkAccess: publicNetworkAccess + inboundIpRules: (empty(inboundIpRules) ? null : inboundIpRules) + } +} + +resource eventGrid_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${eventGrid.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: eventGrid +} + +resource eventGrid_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: eventGrid +} + +module eventGrid_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-EventGrid-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: eventGrid.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module eventGrid_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EventGrid-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: eventGrid.id + } +}] + +@description('The name of the event grid topic') +output name string = eventGrid.name + +@description('The resource ID of the event grid') +output resourceId string = eventGrid.id + +@description('The name of the resource group the event grid was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.EventGrid/topics/readme.md b/carml/1.0.1/Microsoft.EventGrid/topics/readme.md new file mode 100644 index 000000000..88be68250 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/topics/readme.md @@ -0,0 +1,145 @@ +# Event Grid Topics `[Microsoft.EventGrid/topics]` + +This module deploys an event grid topic. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventGrid/topics` | 2020-06-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Event Grid Topic | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DeliveryFailures, PublishFailures]` | `[DeliveryFailures, PublishFailures]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `inboundIpRules` | array | `[]` | | Array of IPs to whitelist. | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `publicNetworkAccess` | string | `'Enabled'` | | Determines if traffic is allowed over public network. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the event grid topic | +| `resourceGroupName` | string | The name of the resource group the event grid was deployed into | +| `resourceId` | string | The resource ID of the event grid | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Topics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2020-06-01/topics) diff --git a/carml/1.0.1/Microsoft.EventGrid/topics/version.json b/carml/1.0.1/Microsoft.EventGrid/topics/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventGrid/topics/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/carml/1.0.1/Microsoft.EventHub/namespaces/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..ac35d182f --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (!empty(privateEndpointObj.customDnsConfigs) ? privateEndpointObj.customDnsConfigs : null) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6c6801dc8 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/.bicep/nested_rbac.bicep @@ -0,0 +1,58 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Schema Registry Contributor (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5dffeca3-4936-4216-b2bc-10343a5abb25') + 'Schema Registry Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2c56ea50-c6b3-40a6-83c0-9d98858bc7d2') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2017-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(eventHubNamespace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: eventHubNamespace +}] diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.EventHub/namespaces/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/.parameters/parameters.json b/carml/1.0.1/Microsoft.EventHub/namespaces/.parameters/parameters.json new file mode 100644 index 000000000..61671781d --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/.parameters/parameters.json @@ -0,0 +1,114 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-evnsp-x-001" + }, + "authorizationRules": { + "value": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "SendListenAccess", + "rights": [ + "Listen", + "Send" + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "eventHubs": { + "value": [ + { + "name": "<>-az-evh-x-001" + }, + { + "name": "<>-az-evh-x-002", + "authorizationRules": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "SendListenAccess", + "rights": [ + "Listen", + "Send" + ] + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "messageRetentionInDays": 1, + "partitionCount": 2, + "status": "Active", + "captureDescriptionEnabled": true, + "captureDescriptionEncoding": "Avro", + "captureDescriptionIntervalInSeconds": 300, + "captureDescriptionSizeLimitInBytes": 314572800, + "captureDescriptionDestinationName": "EventHubArchive.AzureBlockBlob", + "captureDescriptionDestinationStorageAccountResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "captureDescriptionDestinationBlobContainer": "eventhub", + "captureDescriptionDestinationArchiveNameFormat": "{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}", + "captureDescriptionSkipEmptyArchives": true, + "consumerGroups": [ + { + "name": "custom", + "userMetadata": "customMetadata" + } + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/deploy.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/deploy.bicep new file mode 100644 index 000000000..a375bfefc --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/deploy.bicep @@ -0,0 +1,49 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the authorization rule') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource authorizationRule 'Microsoft.EventHub/namespaces/AuthorizationRules@2017-04-01' = { + name: name + parent: namespace + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the resource group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/readme.md b/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/readme.md new file mode 100644 index 000000000..dd72e1f37 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/readme.md @@ -0,0 +1,43 @@ +# EventHub Namespace Authorization Rule `[Microsoft.EventHub/namespaces/authorizationRules]` + +This module deploys an EventHub Namespace Authorization Rule + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/authorizationRules` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule | +| `namespaceName` | string | The name of the event hub namespace | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | The rights associated with the rule. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the resource group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/authorizationRules) diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/version.json b/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/authorizationRules/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/carml/1.0.1/Microsoft.EventHub/namespaces/deploy.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/deploy.bicep new file mode 100644 index 000000000..27ff72b74 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/deploy.bicep @@ -0,0 +1,307 @@ +@description('Optional. The name of the event hub namespace. If no name is provided, then unique name will be created.') +@maxLength(50) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. event hub plan SKU name') +@allowed([ + 'Basic' + 'Standard' +]) +param skuName string = 'Standard' + +@description('Optional. Event Hub plan scale-out capacity of the resource') +@minValue(1) +@maxValue(20) +param skuCapacity int = 1 + +@description('Optional. Switch to make the Event Hub Namespace zone redundant.') +param zoneRedundant bool = false + +@description('Optional. Switch to enable the Auto Inflate feature of Event Hub.') +param isAutoInflateEnabled bool = false + +@description('Optional. Upper limit of throughput units when AutoInflate is enabled, value should be within 0 to 20 throughput units.') +@minValue(0) +@maxValue(20) +param maximumThroughputUnits int = 1 + +@description('Optional. Authorization Rules for the Event Hub namespace') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. Configuration Details for private endpoints.For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints array = [] + +@description('Optional. Service endpoint object information') +param networkAcls object = {} + +@description('Optional. Virtual Network ID to lock down the Event Hub.') +param vNetId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The event hubs to deploy into this namespace') +param eventHubs array = [] + +@description('Optional. The disaster recovery config for this namespace') +param disasterRecoveryConfig object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ArchiveLogs' + 'OperationalLogs' + 'KafkaCoordinatorLogs' + 'KafkaUserErrorLogs' + 'EventHubVNetConnectionEvent' + 'CustomerManagedKeyUserLogs' + 'AutoScaleLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ArchiveLogs' + 'OperationalLogs' + 'KafkaCoordinatorLogs' + 'KafkaUserErrorLogs' + 'EventHubVNetConnectionEvent' + 'CustomerManagedKeyUserLogs' + 'AutoScaleLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +var maxNameLength = 50 +var uniqueEventHubNamespaceUntrim = uniqueString('EventHub Namespace${baseTime}') +var uniqueEventHubNamespace = length(uniqueEventHubNamespaceUntrim) > maxNameLength ? substring(uniqueEventHubNamespaceUntrim, 0, maxNameLength) : uniqueEventHubNamespaceUntrim +var name_var = empty(name) ? uniqueEventHubNamespace : name +var maximumThroughputUnits_var = !isAutoInflateEnabled ? 0 : maximumThroughputUnits +var virtualNetworkRules = [for index in range(0, (empty(networkAcls) ? 0 : length(networkAcls.virtualNetworkRules))): { + id: '${vNetId}/subnets/${networkAcls.virtualNetworkRules[index].subnet}' +}] +var networkAcls_var = { + bypass: !empty(networkAcls) ? networkAcls.bypass : null + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: !empty(networkAcls) ? virtualNetworkRules : null + ipRules: !empty(networkAcls) ? (length(networkAcls.ipRules) > 0 ? networkAcls.ipRules : null) : null +} + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource eventHubNamespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' = { + name: name_var + location: location + tags: tags + identity: identity + sku: { + name: skuName + tier: skuName + capacity: skuCapacity + } + properties: { + zoneRedundant: zoneRedundant + isAutoInflateEnabled: isAutoInflateEnabled + maximumThroughputUnits: maximumThroughputUnits_var + networkAcls: !empty(networkAcls) ? networkAcls_var : null + } +} + +resource eventHubNamespace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${eventHubNamespace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: eventHubNamespace +} + +resource eventHubNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: eventHubNamespace +} + +module eventHubNamespace_eventHubs 'eventhubs/deploy.bicep' = [for (eventHub, index) in eventHubs: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-EventHub-${index}' + params: { + namespaceName: eventHubNamespace.name + name: eventHub.name + authorizationRules: contains(eventHub, 'authorizationRules') ? eventHub.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + captureDescriptionDestinationArchiveNameFormat: contains(eventHub, 'captureDescriptionDestinationArchiveNameFormat') ? eventHub.captureDescriptionDestinationArchiveNameFormat : '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + captureDescriptionDestinationBlobContainer: contains(eventHub, 'captureDescriptionDestinationBlobContainer') ? eventHub.captureDescriptionDestinationBlobContainer : '' + captureDescriptionDestinationName: contains(eventHub, 'captureDescriptionDestinationName') ? eventHub.captureDescriptionDestinationName : 'EventHubArchive.AzureBlockBlob' + captureDescriptionDestinationStorageAccountResourceId: contains(eventHub, 'captureDescriptionDestinationStorageAccountResourceId') ? eventHub.captureDescriptionDestinationStorageAccountResourceId : '' + captureDescriptionEnabled: contains(eventHub, 'captureDescriptionEnabled') ? eventHub.captureDescriptionEnabled : false + captureDescriptionEncoding: contains(eventHub, 'captureDescriptionEncoding') ? eventHub.captureDescriptionEncoding : 'Avro' + captureDescriptionIntervalInSeconds: contains(eventHub, 'captureDescriptionIntervalInSeconds') ? eventHub.captureDescriptionIntervalInSeconds : 300 + captureDescriptionSizeLimitInBytes: contains(eventHub, 'captureDescriptionSizeLimitInBytes') ? eventHub.captureDescriptionSizeLimitInBytes : 314572800 + captureDescriptionSkipEmptyArchives: contains(eventHub, 'captureDescriptionSkipEmptyArchives') ? eventHub.captureDescriptionSkipEmptyArchives : false + consumerGroups: contains(eventHub, 'consumerGroups') ? eventHub.consumerGroups : [] + lock: contains(eventHub, 'lock') ? eventHub.lock : 'NotSpecified' + messageRetentionInDays: contains(eventHub, 'messageRetentionInDays') ? eventHub.messageRetentionInDays : 1 + partitionCount: contains(eventHub, 'partitionCount') ? eventHub.partitionCount : 2 + roleAssignments: contains(eventHub, 'roleAssignments') ? eventHub.roleAssignments : [] + status: contains(eventHub, 'status') ? eventHub.status : 'Active' + } +}] + +module eventHubNamespace_diasterRecoveryConfig 'disasterRecoveryConfigs/deploy.bicep' = if (!empty(disasterRecoveryConfig)) { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-DisRecConfig' + params: { + namespaceName: eventHubNamespace.name + name: disasterRecoveryConfig.name + partnerNamespaceId: contains(disasterRecoveryConfig, 'partnerNamespaceId') ? disasterRecoveryConfig.partnerNamespaceId : '' + } +} + +module eventHubNamespace_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-AuthRule-${index}' + params: { + namespaceName: eventHubNamespace.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module eventHubNamespace_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: eventHubNamespace.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: endpoint + tags: tags + } +}] + +module eventHubNamespace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EvhbNamespace-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: eventHubNamespace.id + } +}] + +@description('The name of the eventspace.') +output name string = eventHubNamespace.name + +@description('The resource ID of the eventspace.') +output resourceId string = eventHubNamespace.id + +@description('The resource group where the namespace is deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(eventHubNamespace.identity, 'principalId') ? eventHubNamespace.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/deploy.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/deploy.bicep new file mode 100644 index 000000000..309056cba --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/deploy.bicep @@ -0,0 +1,44 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the disaster recovery config') +param name string + +@description('Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing') +param partnerNamespaceId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource disasterRecoveryConfig 'Microsoft.EventHub/namespaces/disasterRecoveryConfigs@2017-04-01' = { + name: name + parent: namespace + properties: { + partnerNamespace: partnerNamespaceId + } +} + +@description('The name of the disaster recovery config.') +output name string = disasterRecoveryConfig.name + +@description('The resource ID of the disaster recovery config.') +output resourceId string = disasterRecoveryConfig.id + +@description('The name of the resource group the disaster recovery config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/readme.md b/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/readme.md new file mode 100644 index 000000000..8ff222cfa --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/readme.md @@ -0,0 +1,43 @@ +# EventHub Namespace Disaster Recovery Config `[Microsoft.EventHub/namespaces/disasterRecoveryConfigs]` + +This module deploys an EventHub Namespace Disaster Recovery Config + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/disasterRecoveryConfigs` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disaster recovery config | +| `namespaceName` | string | The name of the event hub namespace | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `partnerNamespaceId` | string | `''` | Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disaster recovery config. | +| `resourceGroupName` | string | The name of the resource group the disaster recovery config was created in. | +| `resourceId` | string | The resource ID of the disaster recovery config. | + +## Template references + +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/disasterRecoveryConfigs) diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/version.json b/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/disasterRecoveryConfigs/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/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..812b8b3a0 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(split(resourceId, '/')[0], split(resourceId, '/')[1], principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: eventHub +}] diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/deploy.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/deploy.bicep new file mode 100644 index 000000000..6c6de03ab --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the event hub namespace event hub') +param eventHubName string + +@description('Required. The name of the authorization rule') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource eventhub 'eventHubs@2021-06-01-preview' existing = { + name: eventHubName + } +} + +resource authorizationRule 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules@2021-06-01-preview' = { + name: name + parent: namespace::eventhub + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the resource group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/readme.md b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/readme.md new file mode 100644 index 000000000..048e9eea3 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/readme.md @@ -0,0 +1,44 @@ +# EventHub Namespace EventHubs Authorization Rule `[Microsoft.EventHub/namespaces/eventhubs/authorizationRules]` + +This module deploys an EventHub Namespace EventHubs Authorization Rule + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/eventhubs/authorizationRules` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `eventHubName` | string | The name of the event hub namespace event hub | +| `name` | string | The name of the authorization rule | +| `namespaceName` | string | The name of the event hub namespace | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | The rights associated with the rule. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the resource group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Eventhubs/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/authorizationRules) diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/version.json b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/authorizationRules/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/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/deploy.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/deploy.bicep new file mode 100644 index 000000000..971bfd30a --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the event hub namespace event hub') +param eventHubName string + +@description('Required. The name of the consumer group') +param name string + +@description('Optional. User Metadata is a placeholder to store user-defined string data with maximum length 1024. e.g. it can be used to store descriptive data, such as list of teams and their contact information also user-defined configuration settings can be stored.') +param userMetadata string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource eventhub 'eventHubs@2021-06-01-preview' existing = { + name: eventHubName + } +} + +resource consumerGroup 'Microsoft.EventHub/namespaces/eventhubs/consumergroups@2021-06-01-preview' = { + name: name + parent: namespace::eventhub + properties: { + userMetadata: !empty(userMetadata) ? userMetadata : null + } +} + +@description('The name of the consumer group.') +output name string = consumerGroup.name + +@description('The resource ID of the consumer group.') +output resourceId string = consumerGroup.id + +@description('The name of the resource group the consumer group was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/readme.md b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/readme.md new file mode 100644 index 000000000..847d5e1f4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/readme.md @@ -0,0 +1,44 @@ +# EventHub Namespace EventHubs Consumer Group `[Microsoft.EventHub/namespaces/eventhubs/consumergroups]` + +This module deploys an EventHub Namespace EventHubs Consumer Group + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.EventHub/namespaces/eventhubs/consumergroups` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `eventHubName` | string | The name of the event hub namespace event hub | +| `name` | string | The name of the consumer group | +| `namespaceName` | string | The name of the event hub namespace | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `userMetadata` | string | `''` | User Metadata is a placeholder to store user-defined string data with maximum length 1024. e.g. it can be used to store descriptive data, such as list of teams and their contact information also user-defined configuration settings can be stored. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the consumer group. | +| `resourceGroupName` | string | The name of the resource group the consumer group was created in. | +| `resourceId` | string | The resource ID of the consumer group. | + +## Template references + +- [Namespaces/Eventhubs/Consumergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/consumergroups) diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/version.json b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/consumergroups/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/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/deploy.bicep b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/deploy.bicep new file mode 100644 index 000000000..d168ba1c5 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. The name of the event hub namespace') +param namespaceName string + +@description('Required. The name of the event hub') +param name string + +@description('Optional. Authorization Rules for the event hub') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. Number of days to retain the events for this Event Hub, value should be 1 to 7 days') +@minValue(1) +@maxValue(7) +param messageRetentionInDays int = 1 + +@description('Optional. Number of partitions created for the Event Hub, allowed values are from 1 to 32 partitions.') +@minValue(1) +@maxValue(32) +param partitionCount int = 2 + +@description('Optional. Enumerates the possible values for the status of the Event Hub.') +@allowed([ + 'Active' + 'Creating' + 'Deleting' + 'Disabled' + 'ReceiveDisabled' + 'Renaming' + 'Restoring' + 'SendDisabled' + 'Unknown' +]) +param status string = 'Active' + +@description('Optional. The consumer groups to create in this event hub instance') +param consumerGroups array = [ + { + name: '$Default' + } +] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Name for capture destination') +param captureDescriptionDestinationName string = 'EventHubArchive.AzureBlockBlob' + +@description('Optional. Blob naming convention for archive, e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}. Here all the parameters (Namespace,EventHub .. etc) are mandatory irrespective of order') +param captureDescriptionDestinationArchiveNameFormat string = '{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}' + +@description('Optional. Blob container Name') +param captureDescriptionDestinationBlobContainer string = '' + +@description('Optional. Resource ID of the storage account to be used to create the blobs') +param captureDescriptionDestinationStorageAccountResourceId string = '' + +@description('Optional. A value that indicates whether capture description is enabled.') +param captureDescriptionEnabled bool = false + +@description('Optional. Enumerates the possible values for the encoding format of capture description. Note: "AvroDeflate" will be deprecated in New API Version') +@allowed([ + 'Avro' + 'AvroDeflate' +]) +param captureDescriptionEncoding string = 'Avro' + +@description('Optional. The time window allows you to set the frequency with which the capture to Azure Blobs will happen') +@minValue(60) +@maxValue(900) +param captureDescriptionIntervalInSeconds int = 300 + +@description('Optional. The size window defines the amount of data built up in your Event Hub before an capture operation') +@minValue(10485760) +@maxValue(524288000) +param captureDescriptionSizeLimitInBytes int = 314572800 + +@description('Optional. A value that indicates whether to Skip Empty Archives') +param captureDescriptionSkipEmptyArchives bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var eventHubPropertiesSimple = { + messageRetentionInDays: messageRetentionInDays + partitionCount: partitionCount + status: status +} +var eventHubPropertiesWithCapture = { + messageRetentionInDays: messageRetentionInDays + partitionCount: partitionCount + status: status + captureDescription: { + destination: { + name: captureDescriptionDestinationName + properties: { + archiveNameFormat: captureDescriptionDestinationArchiveNameFormat + blobContainer: captureDescriptionDestinationBlobContainer + storageAccountResourceId: captureDescriptionDestinationStorageAccountResourceId + } + } + enabled: captureDescriptionEnabled + encoding: captureDescriptionEncoding + intervalInSeconds: captureDescriptionIntervalInSeconds + sizeLimitInBytes: captureDescriptionSizeLimitInBytes + skipEmptyArchives: captureDescriptionSkipEmptyArchives + } +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.EventHub/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource eventHub 'Microsoft.EventHub/namespaces/eventhubs@2021-06-01-preview' = { + name: name + parent: namespace + properties: captureDescriptionEnabled ? eventHubPropertiesWithCapture : eventHubPropertiesSimple +} + +resource eventHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${eventHub.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: eventHub +} + +module eventHub_consumergroups 'consumergroups/deploy.bicep' = [for (consumerGroup, index) in consumerGroups: { + name: '${deployment().name}-ConsumerGroup-${index}' + params: { + namespaceName: namespaceName + eventHubName: eventHub.name + name: consumerGroup.name + userMetadata: contains(consumerGroup, 'userMetadata') ? consumerGroup.userMetadata : '' + } +}] + +module eventHub_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + eventHubName: eventHub.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module eventHub_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: eventHub.id + } +}] + +@description('The name of the event hub.') +output name string = eventHub.name + +@description('The resource ID of the event hub.') +output eventHubId string = eventHub.id + +@description('The resource group the event hub was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The authentication rule resource ID of the event hub.') +output resourceId string = az.resourceId('Microsoft.EventHub/namespaces/authorizationRules', namespaceName, 'RootManageSharedAccessKey') diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/readme.md b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/readme.md new file mode 100644 index 000000000..5e9bc1abf --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/readme.md @@ -0,0 +1,93 @@ +# EventHub `[Microsoft.EventHub/namespaces/eventhubs]` + +This module deploys an Event Hub. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/authorizationRules` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/consumergroups` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the event hub | +| `namespaceName` | string | The name of the event hub namespace | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Authorization Rules for the event hub | +| `captureDescriptionDestinationArchiveNameFormat` | string | `'{Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}'` | | Blob naming convention for archive, e.g. {Namespace}/{EventHub}/{PartitionId}/{Year}/{Month}/{Day}/{Hour}/{Minute}/{Second}. Here all the parameters (Namespace,EventHub .. etc) are mandatory irrespective of order | +| `captureDescriptionDestinationBlobContainer` | string | `''` | | Blob container Name | +| `captureDescriptionDestinationName` | string | `'EventHubArchive.AzureBlockBlob'` | | Name for capture destination | +| `captureDescriptionDestinationStorageAccountResourceId` | string | `''` | | Resource ID of the storage account to be used to create the blobs | +| `captureDescriptionEnabled` | bool | `False` | | A value that indicates whether capture description is enabled. | +| `captureDescriptionEncoding` | string | `'Avro'` | `[Avro, AvroDeflate]` | Enumerates the possible values for the encoding format of capture description. Note: "AvroDeflate" will be deprecated in New API Version | +| `captureDescriptionIntervalInSeconds` | int | `300` | | The time window allows you to set the frequency with which the capture to Azure Blobs will happen | +| `captureDescriptionSizeLimitInBytes` | int | `314572800` | | The size window defines the amount of data built up in your Event Hub before an capture operation | +| `captureDescriptionSkipEmptyArchives` | bool | `False` | | A value that indicates whether to Skip Empty Archives | +| `consumerGroups` | _[consumerGroups](consumerGroups/readme.md)_ array | `[System.Collections.Hashtable]` | | The consumer groups to create in this event hub instance | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `messageRetentionInDays` | int | `1` | | Number of days to retain the events for this Event Hub, value should be 1 to 7 days | +| `partitionCount` | int | `2` | | Number of partitions created for the Event Hub, allowed values are from 1 to 32 partitions. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `status` | string | `'Active'` | `[Active, Creating, Deleting, Disabled, ReceiveDisabled, Renaming, Restoring, SendDisabled, Unknown]` | Enumerates the possible values for the status of the Event Hub. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `eventHubId` | string | The resource ID of the event hub. | +| `name` | string | The name of the event hub. | +| `resourceGroupName` | string | The resource group the event hub was deployed into. | +| `resourceId` | string | The authentication rule resource ID of the event hub. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces/Eventhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs) +- [Namespaces/Eventhubs/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/authorizationRules) +- [Namespaces/Eventhubs/Consumergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/consumergroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/version.json b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/eventhubs/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/carml/1.0.1/Microsoft.EventHub/namespaces/readme.md b/carml/1.0.1/Microsoft.EventHub/namespaces/readme.md new file mode 100644 index 000000000..f6ebc9045 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/readme.md @@ -0,0 +1,180 @@ +# Event Hub Namespaces `[Microsoft.EventHub/namespaces]` + +This module deploys an event hub namespace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventHub/namespaces` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/authorizationRules` | 2017-04-01 | +| `Microsoft.EventHub/namespaces/disasterRecoveryConfigs` | 2017-04-01 | +| `Microsoft.EventHub/namespaces/eventhubs` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/authorizationRules` | 2021-06-01-preview | +| `Microsoft.EventHub/namespaces/eventhubs/consumergroups` | 2021-06-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Authorization Rules for the Event Hub namespace | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ArchiveLogs, OperationalLogs, KafkaCoordinatorLogs, KafkaUserErrorLogs, EventHubVNetConnectionEvent, CustomerManagedKeyUserLogs, AutoScaleLogs]` | `[ArchiveLogs, OperationalLogs, KafkaCoordinatorLogs, KafkaUserErrorLogs, EventHubVNetConnectionEvent, CustomerManagedKeyUserLogs, AutoScaleLogs]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disasterRecoveryConfig` | object | `{object}` | | The disaster recovery config for this namespace | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `eventHubs` | _[eventHubs](eventHubs/readme.md)_ array | `[]` | | The event hubs to deploy into this namespace | +| `isAutoInflateEnabled` | bool | `False` | | Switch to enable the Auto Inflate feature of Event Hub. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maximumThroughputUnits` | int | `1` | | Upper limit of throughput units when AutoInflate is enabled, value should be within 0 to 20 throughput units. | +| `name` | string | `''` | | The name of the event hub namespace. If no name is provided, then unique name will be created. | +| `networkAcls` | object | `{object}` | | Service endpoint object information | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints.For security reasons, it is recommended to use private endpoints whenever possible. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuCapacity` | int | `1` | | Event Hub plan scale-out capacity of the resource | +| `skuName` | string | `'Standard'` | `[Basic, Standard]` | event hub plan SKU name | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vNetId` | string | `''` | | Virtual Network ID to lock down the Event Hub. | +| `zoneRedundant` | bool | `False` | | Switch to make the Event Hub Namespace zone redundant. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a SAS token to access the modules. | + + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the eventspace. | +| `resourceGroupName` | string | The resource group where the namespace is deployed. | +| `resourceId` | string | The resource ID of the eventspace. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces) +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/authorizationRules) +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2017-04-01/namespaces/disasterRecoveryConfigs) +- [Namespaces/Eventhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs) +- [Namespaces/Eventhubs/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/authorizationRules) +- [Namespaces/Eventhubs/Consumergroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventHub/2021-06-01-preview/namespaces/eventhubs/consumergroups) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.EventHub/namespaces/version.json b/carml/1.0.1/Microsoft.EventHub/namespaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.EventHub/namespaces/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/carml/1.0.1/Microsoft.HealthBot/healthBots/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.HealthBot/healthBots/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c0a43f57c --- /dev/null +++ b/carml/1.0.1/Microsoft.HealthBot/healthBots/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource healthBot 'Microsoft.HealthBot/healthBots@2021-06-10' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(healthBot.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: healthBot +}] diff --git a/carml/1.0.1/Microsoft.HealthBot/healthBots/.parameters/parameters.json b/carml/1.0.1/Microsoft.HealthBot/healthBots/.parameters/parameters.json new file mode 100644 index 000000000..76b924cc3 --- /dev/null +++ b/carml/1.0.1/Microsoft.HealthBot/healthBots/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ahb-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.HealthBot/healthBots/deploy.bicep b/carml/1.0.1/Microsoft.HealthBot/healthBots/deploy.bicep new file mode 100644 index 000000000..cf434040b --- /dev/null +++ b/carml/1.0.1/Microsoft.HealthBot/healthBots/deploy.bicep @@ -0,0 +1,76 @@ +@description('Required. Name of the resource') +param name string + +@description('Optional. The resource model definition representing SKU.') +param sku string = 'F0' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource azureHealthBot 'Microsoft.HealthBot/healthBots@2020-12-08' = { + name: name + location: location + tags: tags + sku: { + name: sku + } + properties: {} +} + +resource azureHealthBot_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureHealthBot.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureHealthBot +} + +module healthBot_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-HealthBot-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureHealthBot.id + } +}] + +@description('The resource group the health bot was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the health bot') +output name string = azureHealthBot.name + +@description('The resource ID of the health bot') +output resourceId string = azureHealthBot.id diff --git a/carml/1.0.1/Microsoft.HealthBot/healthBots/readme.md b/carml/1.0.1/Microsoft.HealthBot/healthBots/readme.md new file mode 100644 index 000000000..0d2a4870e --- /dev/null +++ b/carml/1.0.1/Microsoft.HealthBot/healthBots/readme.md @@ -0,0 +1,93 @@ +# Azure Health Bots `[Microsoft.HealthBot/healthBots]` + +This module deploys an Azure Health Bot. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.HealthBot/healthBots` | 2020-12-08 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the resource | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'F0'` | | The resource model definition representing SKU. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the health bot | +| `resourceGroupName` | string | The resource group the health bot was deployed into | +| `resourceId` | string | The resource ID of the health bot | + +## Template references + +- [Healthbots](https://docs.microsoft.com/en-us/azure/templates/Microsoft.HealthBot/2020-12-08/healthBots) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.HealthBot/healthBots/version.json b/carml/1.0.1/Microsoft.HealthBot/healthBots/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.HealthBot/healthBots/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/carml/1.0.1/Microsoft.Insights/actionGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Insights/actionGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..dc1368efc --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/actionGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,54 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource actionGroup 'microsoft.insights/actionGroups@2019-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(actionGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: actionGroup +}] diff --git a/carml/1.0.1/Microsoft.Insights/actionGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/actionGroups/.parameters/parameters.json new file mode 100644 index 000000000..32c9e7606 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/actionGroups/.parameters/parameters.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ag-x-001" + }, + "groupShortName": { + "value": "azagweux001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "emailReceivers": { + "value": [ + { + "name": "TestUser_-EmailAction-", + "emailAddress": "test.user@testcompany.com", + "useCommonAlertSchema": true + }, + { + "name": "TestUser2", + "emailAddress": "test.user2@testcompany.com", + "useCommonAlertSchema": true + } + ] + }, + "smsReceivers": { + "value": [ + { + "name": "TestUser_-SMSAction-", + "countryCode": "1", + "phoneNumber": "2345678901" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/actionGroups/deploy.bicep b/carml/1.0.1/Microsoft.Insights/actionGroups/deploy.bicep new file mode 100644 index 000000000..da1866b7e --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/actionGroups/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. The name of the action group.') +param name string + +@description('Required. The short name of the action group.') +param groupShortName string + +@description('Optional. Indicates whether this action group is enabled. If an action group is not enabled, then none of its receivers will receive communications.') +param enabled bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The list of email receivers that are part of this action group.') +param emailReceivers array = [] + +@description('Optional. The list of SMS receivers that are part of this action group.') +param smsReceivers array = [] + +@description('Optional. The list of webhook receivers that are part of this action group.') +param webhookReceivers array = [] + +@description('Optional. The list of ITSM receivers that are part of this action group.') +param itsmReceivers array = [] + +@description('Optional. The list of AzureAppPush receivers that are part of this action group.') +param azureAppPushReceivers array = [] + +@description('Optional. The list of AutomationRunbook receivers that are part of this action group.') +param automationRunbookReceivers array = [] + +@description('Optional. The list of voice receivers that are part of this action group.') +param voiceReceivers array = [] + +@description('Optional. The list of logic app receivers that are part of this action group.') +param logicAppReceivers array = [] + +@description('Optional. The list of function receivers that are part of this action group.') +param azureFunctionReceivers array = [] + +@description('Optional. The list of ARM role receivers that are part of this action group. Roles are Azure RBAC roles and only built-in roles are supported.') +param armRoleReceivers array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Location for all resources.') +param location string = 'global' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource actionGroup 'microsoft.insights/actionGroups@2019-06-01' = { + name: name + location: location + tags: tags + properties: { + groupShortName: groupShortName + enabled: enabled + emailReceivers: (empty(emailReceivers) ? null : emailReceivers) + smsReceivers: (empty(smsReceivers) ? null : smsReceivers) + webhookReceivers: (empty(webhookReceivers) ? null : webhookReceivers) + itsmReceivers: (empty(itsmReceivers) ? null : itsmReceivers) + azureAppPushReceivers: (empty(azureAppPushReceivers) ? null : azureAppPushReceivers) + automationRunbookReceivers: (empty(automationRunbookReceivers) ? null : automationRunbookReceivers) + voiceReceivers: (empty(voiceReceivers) ? null : voiceReceivers) + logicAppReceivers: (empty(logicAppReceivers) ? null : logicAppReceivers) + azureFunctionReceivers: (empty(azureFunctionReceivers) ? null : azureFunctionReceivers) + armRoleReceivers: (empty(armRoleReceivers) ? null : armRoleReceivers) + } +} + +module actionGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ActionGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: actionGroup.id + } +}] + +@description('The resource group the action group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the action group ') +output name string = actionGroup.name + +@description('The resource ID of the action group ') +output resourceId string = actionGroup.id diff --git a/carml/1.0.1/Microsoft.Insights/actionGroups/readme.md b/carml/1.0.1/Microsoft.Insights/actionGroups/readme.md new file mode 100644 index 000000000..7d1557233 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/actionGroups/readme.md @@ -0,0 +1,145 @@ +# Action Groups `[Microsoft.Insights/actionGroups]` + +This module deploys an Action Group. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `microsoft.insights/actionGroups` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `groupShortName` | string | The short name of the action group. | +| `name` | string | The name of the action group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `armRoleReceivers` | array | `[]` | The list of ARM role receivers that are part of this action group. Roles are Azure RBAC roles and only built-in roles are supported. | +| `automationRunbookReceivers` | array | `[]` | The list of AutomationRunbook receivers that are part of this action group. | +| `azureAppPushReceivers` | array | `[]` | The list of AzureAppPush receivers that are part of this action group. | +| `azureFunctionReceivers` | array | `[]` | The list of function receivers that are part of this action group. | +| `emailReceivers` | array | `[]` | The list of email receivers that are part of this action group. | +| `enabled` | bool | `True` | Indicates whether this action group is enabled. If an action group is not enabled, then none of its receivers will receive communications. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `itsmReceivers` | array | `[]` | The list of ITSM receivers that are part of this action group. | +| `location` | string | `'global'` | Location for all resources. | +| `logicAppReceivers` | array | `[]` | The list of logic app receivers that are part of this action group. | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `smsReceivers` | array | `[]` | The list of SMS receivers that are part of this action group. | +| `tags` | object | `{object}` | Tags of the resource. | +| `voiceReceivers` | array | `[]` | The list of voice receivers that are part of this action group. | +| `webhookReceivers` | array | `[]` | The list of webhook receivers that are part of this action group. | + + +### Parameter Usage: receivers + +See [Documentation](https://docs.microsoft.com/en-us/azure/templates/microsoft.insights/2019-06-01/actiongroups) for description of parameters usage and syntax. + +Example: + +```json +"emailReceivers":{ + "value":[ + { + "name": "TestUser_-EmailAction-", + "emailAddress": "test.user@testcompany.com", + "useCommonAlertSchema": true + }, + { + "name": "TestUser2", + "emailAddress": "test.user2@testcompany.com", + "useCommonAlertSchema": true + } + ] +}, +"smsReceivers":{ + "value": [ + { + "name": "TestUser_-SMSAction-", + "countryCode": "1", + "phoneNumber": "2345678901" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Additional notes on parameters + +- Receiver name must be unique across the ActionGroup +- Email, SMS, Azure App push and Voice can be grouped in the same Action. To do so, the `name` field of the receivers must be in the `RecName_-ActionType-` format where: + - _RecName_ is the name you want to give to the Action + - _ActionType_ is one of the action types that can be grouped together. Possible values are: + - EmailAction + - SMSAction + - AzureAppAction + - VoiceAction +- To understand the impact of the `useCommonAlertSchema` field, see [here](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/alerts-common-schema) + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the action group | +| `resourceGroupName` | string | The resource group the action group was deployed into | +| `resourceId` | string | The resource ID of the action group | + +## Template references + +- [Actiongroups](https://docs.microsoft.com/en-us/azure/templates/microsoft.insights/2019-06-01/actionGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Insights/actionGroups/version.json b/carml/1.0.1/Microsoft.Insights/actionGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/actionGroups/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/carml/1.0.1/Microsoft.Insights/activityLogAlerts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b2b94a054 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/.bicep/nested_rbac.bicep @@ -0,0 +1,54 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(activityLogAlert.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: activityLogAlert +}] diff --git a/carml/1.0.1/Microsoft.Insights/activityLogAlerts/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/.parameters/parameters.json new file mode 100644 index 000000000..8d7e3e658 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/.parameters/parameters.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ala-x-001" + }, + "scopes": { + "value": [ + "/subscriptions/<>" + ] + }, + "conditions": { + "value": [ + { + "field": "category", + "equals": "Administrative" + }, + { + "field": "resourceType", + "equals": "microsoft.compute/virtualmachines" + }, + { + "field": "operationName", + "equals": "Microsoft.Compute/virtualMachines/performMaintenance/action" + } + ] + }, + "actions": { + "value": [ + { + "actionGroupId": "/subscriptions/<>/resourceGroups/validation-rg/providers/microsoft.insights/actiongroups/adp-<>-az-ag-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/activityLogAlerts/deploy.bicep b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/deploy.bicep new file mode 100644 index 000000000..07efbf5a0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/deploy.bicep @@ -0,0 +1,85 @@ +@description('Required. The name of the alert.') +param name string + +@description('Optional. Description of the alert.') +param alertDescription string = '' + +@description('Optional. Location for all resources.') +param location string = 'global' + +@description('Optional. Indicates whether this alert is enabled.') +param enabled bool = true + +@description('Required. the list of resource IDs that this metric alert is scoped to.') +param scopes array = [ + subscription().id +] + +@description('Optional. The list of actions to take when alert triggers.') +param actions array = [] + +@description('Required. The condition that will cause this alert to activate. Array of objects') +param conditions array + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var actionGroups = [for action in actions: { + actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action + webhookProperties: contains(action, 'webhookProperties') ? action.webhookProperties : null +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = { + name: name + location: location + tags: tags + properties: { + scopes: scopes + condition: { + allOf: conditions + } + actions: { + actionGroups: actionGroups + } + enabled: enabled + description: alertDescription + } +} + +module activityLogAlert_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ActivityLogAlert-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: activityLogAlert.id + } +}] + +@description('The name of the activity log alert') +output name string = activityLogAlert.name + +@description('The resource ID of the activity log alert') +output resourceId string = activityLogAlert.id + +@description('The resource group the activity log alert was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Insights/activityLogAlerts/readme.md b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/readme.md new file mode 100644 index 000000000..69999cb35 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/readme.md @@ -0,0 +1,199 @@ +# Activity Log Alerts `[Microsoft.Insights/activityLogAlerts]` + +This module deploys an Alert based on Activity Log. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/activityLogAlerts` | 2020-10-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `conditions` | array | | The condition that will cause this alert to activate. Array of objects | +| `name` | string | | The name of the alert. | +| `scopes` | array | `[[subscription().id]]` | the list of resource IDs that this metric alert is scoped to. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | The list of actions to take when alert triggers. | +| `alertDescription` | string | `''` | Description of the alert. | +| `enabled` | bool | `True` | Indicates whether this alert is enabled. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `'global'` | Location for all resources. | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | Tags of the resource. | + + +### Parameter Usage: actions + +```json +"actions": { + "value": [ + { + "actionGroupId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/actionGroupName", + "webhookProperties": {} + } + ] +} +``` + +`webhookProperties` is optional. + +If you do only want to provide actionGroupIds, a shorthand use of the parameter is available. + +```json +"actions": { + "value": [ + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/actionGroupName" + ] +} +``` + +### Parameter Usage: conditions + +**Conditions can also be combined with logical operators `allOf` and `anyOf`** + +```json +{ + "field": "string", + "equals": "string", + "containsAny": "array" +} +``` + +Each condition can specify only one field between `equals` and `containsAny`. + +| Parameter Name | Type | Possible values | Description | +| :------------- | :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | +| `field` | string | `resourceId`,
    `category`,
    `caller`,
    `level`,
    `operationName`,
    `resourceGroup`,
    `resourceProvider`,
    `status`,
    `subStatus`,
    `resourceType`,
    or anything beginning with `properties.` | Required. The name of the field that this condition will examine. | +| `equals` | string | | Optional (Alternative to `containsAny`). The value to confront with. | +| `containsAny` | array of strings | | Optional (Alternative to `equals`). Condition will be satisfied if value of the field in the event is within one of the specified here. | + +**Sample** + +```json +"conditions":{ + "value": [ + { + "field": "category", + "equals": "Administrative" + }, + { + "field": "resourceType", + "equals": "microsoft.compute/virtualmachines" + }, + { + "field": "operationName", + "equals": "Microsoft.Compute/virtualMachines/performMaintenance/action" + } + ] +} +``` + +**Sample 2** + +```json +"conditions":{ + "value": [ + { + "field": "category", + "equals": "ServiceHealth" + }, + { + "anyOf": [ + { + "field": "properties.incidentType", + "equals": "Incident" + }, + { + "field": "properties.incidentType", + "equals": "Maintenance" + } + ] + }, + { + "field": "properties.impactedServices[*].ServiceName", + "containsAny": [ + "Action Groups", + "Activity Logs & Alerts" + ] + }, + { + "field": "properties.impactedServices[*].ImpactedRegions[*].RegionName", + "containsAny": [ + "West Europe", + "Global" + ] + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the activity log alert | +| `resourceGroupName` | string | The resource group the activity log alert was deployed into | +| `resourceId` | string | The resource ID of the activity log alert | + +## Template references + +- [Activitylogalerts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2020-10-01/activityLogAlerts) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Insights/activityLogAlerts/version.json b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/activityLogAlerts/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/carml/1.0.1/Microsoft.Insights/components/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Insights/components/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d131a6ae7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/components/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Application Insights Snapshot Debugger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') +} + +resource appInsights 'Microsoft.Insights/components@2020-02-02' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appInsights.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: appInsights +}] diff --git a/carml/1.0.1/Microsoft.Insights/components/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/components/.parameters/parameters.json new file mode 100644 index 000000000..636d9f6c7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/components/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-appi-x-001" + }, + "workspaceResourceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-appi-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/components/deploy.bicep b/carml/1.0.1/Microsoft.Insights/components/deploy.bicep new file mode 100644 index 000000000..69568f350 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/components/deploy.bicep @@ -0,0 +1,110 @@ +@description('Required. Name of the Application Insights') +param name string + +@description('Optional. Application type') +@allowed([ + 'web' + 'other' +]) +param appInsightsType string = 'web' + +@description('Required. Resource ID of the log analytics workspace which the data will be ingested to. This property is required to create an application with this API version. Applications from older versions will not have this property.') +param workspaceResourceId string + +@description('Optional. The network access type for accessing Application Insights ingestion. - Enabled or Disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Optional. The network access type for accessing Application Insights query. - Enabled or Disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Optional. Retention period in days.') +@allowed([ + 30 + 60 + 90 + 120 + 180 + 270 + 365 + 550 + 730 +]) +param retentionInDays int = 365 + +@description('Optional. Percentage of the data produced by the application being monitored that is being sampled for Application Insights telemetry.') +@minValue(0) +@maxValue(100) +param samplingPercentage int = 100 + +@description('Optional. The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone.') +param kind string = '' + +@description('Optional. Location for all Resources') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource appInsights 'Microsoft.Insights/components@2020-02-02' = { + name: name + location: location + tags: tags + kind: kind + properties: { + Application_Type: appInsightsType + WorkspaceResourceId: workspaceResourceId + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + RetentionInDays: retentionInDays + SamplingPercentage: samplingPercentage + } +} + +module appInsights_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppInsights-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appInsights.id + } +}] + +@description('The name of the application insights component') +output name string = appInsights.name + +@description('The resource ID of the application insights component') +output resourceId string = appInsights.id + +@description('The resource group the application insights component was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The application ID of the application insights component') +output applicationId string = appInsights.properties.AppId diff --git a/carml/1.0.1/Microsoft.Insights/components/readme.md b/carml/1.0.1/Microsoft.Insights/components/readme.md new file mode 100644 index 000000000..dd0310dc5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/components/readme.md @@ -0,0 +1,95 @@ +# Application Insights `[Microsoft.Insights/components]` + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/components` | 2020-02-02 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Application Insights | +| `workspaceResourceId` | string | Resource ID of the log analytics workspace which the data will be ingested to. This property is required to create an application with this API version. Applications from older versions will not have this property. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appInsightsType` | string | `'web'` | `[web, other]` | Application type | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `kind` | string | `''` | | The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone. | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources | +| `publicNetworkAccessForIngestion` | string | `'Enabled'` | `[Enabled, Disabled]` | The network access type for accessing Application Insights ingestion. - Enabled or Disabled | +| `publicNetworkAccessForQuery` | string | `'Enabled'` | `[Enabled, Disabled]` | The network access type for accessing Application Insights query. - Enabled or Disabled | +| `retentionInDays` | int | `365` | `[30, 60, 90, 120, 180, 270, 365, 550, 730]` | Retention period in days. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `samplingPercentage` | int | `100` | | Percentage of the data produced by the application being monitored that is being sampled for Application Insights telemetry. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationId` | string | The application ID of the application insights component | +| `name` | string | The name of the application insights component | +| `resourceGroupName` | string | The resource group the application insights component was deployed into | +| `resourceId` | string | The resource ID of the application insights component | + +## Template references + +- [Components](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2020-02-02/components) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Insights/components/version.json b/carml/1.0.1/Microsoft.Insights/components/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/components/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/carml/1.0.1/Microsoft.Insights/diagnosticSettings/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/.parameters/parameters.json new file mode 100644 index 000000000..2e1d38512 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-diag-x-001" + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/diagnosticSettings/deploy.bicep b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/deploy.bicep new file mode 100644 index 000000000..c07bc8058 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/deploy.bicep @@ -0,0 +1,93 @@ +targetScope = 'subscription' + +@description('Optional. Name of the ActivityLog diagnostic settings.') +@minLength(1) +@maxLength(260) +param name string = '${uniqueString(subscription().id)}-ActivityLog' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Administrative' + 'Security' + 'ServiceHealth' + 'Alert' + 'Recommendation' + 'Policy' + 'Autoscale' + 'ResourceHealth' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Administrative' + 'Security' + 'ServiceHealth' + 'Alert' + 'Recommendation' + 'Policy' + 'Autoscale' + 'ResourceHealth' +] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource diagnosticSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: name + properties: { + storageAccountId: (empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId) + workspaceId: (empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId) + eventHubAuthorizationRuleId: (empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId) + eventHubName: (empty(diagnosticEventHubName) ? null : diagnosticEventHubName) + logs: ((empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName)) ? null : diagnosticsLogs) + } +} + +@description('The name of the diagnostic settings') +output name string = diagnosticSetting.name + +@description('The resource ID of the diagnostic settings') +output resourceId string = diagnosticSetting.id + +@description('The name of the subscription to deploy into') +output subscriptionName string = subscription().displayName diff --git a/carml/1.0.1/Microsoft.Insights/diagnosticSettings/readme.md b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/readme.md new file mode 100644 index 000000000..7b39cf83f --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/readme.md @@ -0,0 +1,44 @@ +# Activity Logs `[Microsoft.Insights/diagnosticSettings]` + +This module deploys a subscription wide export of the activity log. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Administrative, Security, ServiceHealth, Alert, Recommendation, Policy, Autoscale, ResourceHealth]` | `[Administrative, Security, ServiceHealth, Alert, Recommendation, Policy, Autoscale, ResourceHealth]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `name` | string | `[format('{0}-ActivityLog', uniqueString(subscription().id))]` | | Name of the ActivityLog diagnostic settings. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the diagnostic settings | +| `resourceId` | string | The resource ID of the diagnostic settings | +| `subscriptionName` | string | The name of the subscription to deploy into | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) diff --git a/carml/1.0.1/Microsoft.Insights/diagnosticSettings/version.json b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/diagnosticSettings/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/carml/1.0.1/Microsoft.Insights/metricAlerts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Insights/metricAlerts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b7c5db39e --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/metricAlerts/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource metricAlert 'Microsoft.Insights/metricAlerts@2018-03-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(metricAlert.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: metricAlert +}] diff --git a/carml/1.0.1/Microsoft.Insights/metricAlerts/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/metricAlerts/.parameters/parameters.json new file mode 100644 index 000000000..bbe65cdae --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/metricAlerts/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ma-x-001" + }, + "windowSize": { + "value": "PT15M" + }, + "actions": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/microsoft.insights/actiongroups/adp-<>-az-ag-x-001" + ] + }, + "targetResourceType": { + "value": "microsoft.compute/virtualmachines" + }, + "targetResourceRegion": { + "value": "westeurope" + }, + "criterias": { + "value": [ + { + "criterionType": "StaticThresholdCriterion", + "metricName": "Percentage CPU", + "metricNamespace": "microsoft.compute/virtualmachines", + "name": "HighCPU", + "operator": "GreaterThan", + "threshold": "90", + "timeAggregation": "Average" + } + ] + }, + "alertCriteriaType": { + "value": "Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/metricAlerts/deploy.bicep b/carml/1.0.1/Microsoft.Insights/metricAlerts/deploy.bicep new file mode 100644 index 000000000..2d3c8e151 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/metricAlerts/deploy.bicep @@ -0,0 +1,140 @@ +@description('Required. The name of the alert.') +param name string + +@description('Optional. Description of the alert.') +param alertDescription string = '' + +@description('Optional. Location for all resources.') +param location string = 'global' + +@description('Optional. Indicates whether this alert is enabled.') +param enabled bool = true + +@description('Optional. The severity of the alert.') +@allowed([ + 0 + 1 + 2 + 3 + 4 +]) +param severity int = 3 + +@description('Optional. how often the metric alert is evaluated represented in ISO 8601 duration format.') +@allowed([ + 'PT1M' + 'PT5M' + 'PT15M' + 'PT30M' + 'PT1H' +]) +param evaluationFrequency string = 'PT5M' + +@description('Optional. the period of time (in ISO 8601 duration format) that is used to monitor alert activity based on the threshold.') +@allowed([ + 'PT1M' + 'PT5M' + 'PT15M' + 'PT30M' + 'PT1H' + 'PT6H' + 'PT12H' + 'P1D' +]) +param windowSize string = 'PT15M' + +@description('Optional. the list of resource IDs that this metric alert is scoped to.') +param scopes array = [ + subscription().id +] + +@description('Optional. The resource type of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria.') +param targetResourceType string = '' + +@description('Optional. The region of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria.') +param targetResourceRegion string = '' + +@description('Optional. The flag that indicates whether the alert should be auto resolved or not.') +param autoMitigate bool = true + +@description('Optional. The list of actions to take when alert triggers.') +param actions array = [] + +@description('Optional. Maps to the \'odata.type\' field. Specifies the type of the alert criteria.') +@allowed([ + 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria' + 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' + 'Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria' +]) +param alertCriteriaType string = 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' + +@description('Required. Criterias to trigger the alert. Array of \'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria\' or \'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria\' objects') +param criterias array + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var actionGroups = [for action in actions: { + actionGroupId: contains(action, 'actionGroupId') ? action.actionGroupId : action + webHookProperties: contains(action, 'webHookProperties') ? action.webHookProperties : null +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource metricAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = { + name: name + location: location + tags: tags + properties: { + description: alertDescription + severity: severity + enabled: enabled + scopes: scopes + evaluationFrequency: evaluationFrequency + windowSize: windowSize + targetResourceType: targetResourceType + targetResourceRegion: targetResourceRegion + criteria: { + 'odata.type': alertCriteriaType + allOf: criterias + } + autoMitigate: autoMitigate + actions: actionGroups + } +} + +module metricAlert_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-MetricAlert-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: metricAlert.id + } +}] + +@description('The resource group the metric alert was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the metric alert') +output name string = metricAlert.name + +@description('The resource ID of the metric alert') +output resourceId string = metricAlert.id diff --git a/carml/1.0.1/Microsoft.Insights/metricAlerts/readme.md b/carml/1.0.1/Microsoft.Insights/metricAlerts/readme.md new file mode 100644 index 000000000..f4133a9ff --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/metricAlerts/readme.md @@ -0,0 +1,189 @@ +# Metric Alerts `[Microsoft.Insights/metricAlerts]` + +This module deploys an alert based on metrics. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/metricAlerts` | 2018-03-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `criterias` | array | Criterias to trigger the alert. Array of 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria' or 'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria' objects | +| `name` | string | The name of the alert. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | The list of actions to take when alert triggers. | +| `alertCriteriaType` | string | `'Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria'` | `[Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria, Microsoft.Azure.Monitor.MultipleResourceMultipleMetricCriteria, Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria]` | Maps to the 'odata.type' field. Specifies the type of the alert criteria. | +| `alertDescription` | string | `''` | | Description of the alert. | +| `autoMitigate` | bool | `True` | | The flag that indicates whether the alert should be auto resolved or not. | +| `enabled` | bool | `True` | | Indicates whether this alert is enabled. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `evaluationFrequency` | string | `'PT5M'` | `[PT1M, PT5M, PT15M, PT30M, PT1H]` | how often the metric alert is evaluated represented in ISO 8601 duration format. | +| `location` | string | `'global'` | | Location for all resources. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scopes` | array | `[[subscription().id]]` | | the list of resource IDs that this metric alert is scoped to. | +| `severity` | int | `3` | `[0, 1, 2, 3, 4]` | The severity of the alert. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `targetResourceRegion` | string | `''` | | The region of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria. | +| `targetResourceType` | string | `''` | | The resource type of the target resource(s) on which the alert is created/updated. Mandatory for MultipleResourceMultipleMetricCriteria. | +| `windowSize` | string | `'PT15M'` | `[PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H, P1D]` | the period of time (in ISO 8601 duration format) that is used to monitor alert activity based on the threshold. | + + +### Parameter Usage: actions + +```json +"actions": { + "value": [ + { + "actionGroupId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/ActionGroupName", + "webhookProperties": {} + } + ] +} +``` + +`webhookProperties` is optional. + +If you do only want to provide actionGroupIds, a shorthand use of the parameter is available. + +```json +"actions": { + "value": [ + "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rgName/providers/microsoft.insights/actiongroups/actionGroupName" + ] +} +``` + +### Parameter Usage: criterias + +**SingleResourceMultipleMetricCriteria** + +```json +{ + "criterionType": "string", + "dimensions": [], + "metricName": "string", + "metricNamespace": "string", + "name": "string", + "operator": "string", + "threshold": "integer", + "timeAggregation": "string" +} +``` + +**MultipleResourceMultipleMetricCriteria** + +```json +{ + "criterionType": "string", + "dimensions": [], + "metricName": "string", + "metricNamespace": "string", + "name": "string", + "operator": "string", + "threshold": "integer", + "timeAggregation": "string", + "alertSensitivity": "string", + "failingPeriods": { + "minFailingPeriodsToAlert": "integer", + "numberOfEvaluationPeriods": "integer" + }, + "ignoreDataBefore": "string" +} +``` + +**Sample** +The following sample can be use both for Single and Multiple criterias. The other parameters are optional. + +```json +"criterias":{ + "value": [ + { + "criterionType": "StaticThresholdCriterion", + "metricName": "Percentage CPU", + "metricNamespace": "microsoft.compute/virtualmachines", + "name": "HighCPU", + "operator": "GreaterThan", + "threshold": "90", + "timeAggregation": "Average" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Additional notes on parameters + +- When using MultipleResourceMultipleMetricCriteria criteria type, some parameters becomes mandatory (see above) +- MultipleResourceMultipleMetricCriteria is suggested, as additional scopes can be added later +- It's not possible to convert from SingleResourceMultipleMetricCriteria to MultipleResourceMultipleMetricCriteria. Delete and re-create the alert. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the metric alert | +| `resourceGroupName` | string | The resource group the metric alert was deployed into | +| `resourceId` | string | The resource ID of the metric alert | + +## Template references + +- [Metricalerts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2018-03-01/metricAlerts) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Insights/metricAlerts/version.json b/carml/1.0.1/Microsoft.Insights/metricAlerts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/metricAlerts/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/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..5672ec5ea --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateDnsZoneGroups 'privateDnsZoneGroups@2021-05-01' = { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..958030566 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateLinkScope 'Microsoft.Insights/privateLinkScopes@2019-10-17-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateLinkScope.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: privateLinkScope +}] diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.parameters/parameters.json new file mode 100644 index 000000000..26b710302 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/.parameters/parameters.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pls-x-001" + }, + "scopedResources": { + "value": [ + { + "name": "scoped1", + "linkedResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/deploy.bicep b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/deploy.bicep new file mode 100644 index 000000000..8b71395eb --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/deploy.bicep @@ -0,0 +1,96 @@ +@description('Required. Name of the private link scope.') +@minLength(1) +param name string + +@description('Optional. The location of the private link scope. Should be global.') +param location string = 'global' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for Azure Monitor Resources.') +param scopedResources array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateLinkScope 'Microsoft.Insights/privateLinkScopes@2019-10-17-preview' = { + name: name + location: location + tags: tags + properties: {} +} + +module privateLinkScope_scopedResource 'scopedResources/deploy.bicep' = [for (scopedResource, index) in scopedResources: { + name: '${uniqueString(deployment().name, location)}-PvtLinkScope-ScopedRes-${index}' + params: { + name: scopedResource.name + privateLinkScopeName: privateLinkScope.name + linkedResourceId: scopedResource.linkedResourceId + } +}] + +resource privateLinkScope_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateLinkScope.name}-${lock}-lock' + scope: privateLinkScope + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } +} + +module privateLinkScope_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-PvtLinkScope-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: privateLinkScope.id + privateEndpointVnetLocation: reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: endpoint + tags: tags + } +}] + +module privateLinkScope_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PvtLinkScope-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateLinkScope.id + } +}] + +@description('The name of the private link scope') +output name string = privateLinkScope.name + +@description('The resource ID of the private link scope') +output resourceId string = privateLinkScope.id + +@description('The resource group the private link scope was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/readme.md b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/readme.md new file mode 100644 index 000000000..ef75ac386 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/readme.md @@ -0,0 +1,136 @@ +# Azure Monitor Private Link Scopes `[Microsoft.Insights/privateLinkScopes]` + +This module deploys an Azure Monitor Private Link Scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `microsoft.insights/privateLinkScopes` | 2019-10-17-preview | +| `Microsoft.Insights/privateLinkScopes/scopedResources` | 2021-07-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the private link scope. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `'global'` | | The location of the private link scope. Should be global. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scopedResources` | _[scopedResources](scopedResources/readme.md)_ array | `[]` | | Configuration Details for Azure Monitor Resources. | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private link scope | +| `resourceGroupName` | string | The resource group the private link scope was deployed into | +| `resourceId` | string | The resource ID of the private link scope | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Privatelinkscopes](https://docs.microsoft.com/en-us/azure/templates/microsoft.insights/2019-10-17-preview/privateLinkScopes) +- [Privatelinkscopes/Scopedresources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-07-01-preview/privateLinkScopes/scopedResources) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/deploy.bicep b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/deploy.bicep new file mode 100644 index 000000000..977b762b2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/deploy.bicep @@ -0,0 +1,46 @@ +@description('Required. Name of the private link scoped resource.') +@minLength(1) +param name string + +@description('Required. Name of the parent private link scope.') +@minLength(1) +param privateLinkScopeName string + +@description('Required. The resource ID of the scoped Azure monitor resource.') +param linkedResourceId string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateLinkScope 'microsoft.insights/privateLinkScopes@2021-07-01-preview' existing = { + name: privateLinkScopeName +} + +resource scopedResource 'Microsoft.Insights/privateLinkScopes/scopedResources@2021-07-01-preview' = { + name: name + parent: privateLinkScope + properties: { + linkedResourceId: linkedResourceId + } +} + +@description('The name of the resource group where the resource has been deployed') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the deployed scopedResource') +output resourceId string = scopedResource.id + +@description('The full name of the deployed Scoped Resource') +output name string = scopedResource.name diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/readme.md b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/readme.md new file mode 100644 index 000000000..78728cd0b --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/readme.md @@ -0,0 +1,43 @@ +# Insights PrivateLinkScopes ScopedResources `[Microsoft.Insights/privateLinkScopes/scopedResources]` + +This module deploys Insights PrivateLinkScopes ScopedResources. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/privateLinkScopes/scopedResources` | 2021-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `linkedResourceId` | string | The resource ID of the scoped Azure monitor resource. | +| `name` | string | Name of the private link scoped resource. | +| `privateLinkScopeName` | string | Name of the parent private link scope. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The full name of the deployed Scoped Resource | +| `resourceGroupName` | string | The name of the resource group where the resource has been deployed | +| `resourceId` | string | The resource ID of the deployed scopedResource | + +## Template references + +- [Privatelinkscopes/Scopedresources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-07-01-preview/privateLinkScopes/scopedResources) diff --git a/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/version.json b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/scopedResources/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/carml/1.0.1/Microsoft.Insights/privateLinkScopes/version.json b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/privateLinkScopes/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/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..3e94006b0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource queryAlert 'microsoft.insights/scheduledQueryRules@2018-04-16' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queryAlert.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: queryAlert +}] diff --git a/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/.parameters/parameters.json b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/.parameters/parameters.json new file mode 100644 index 000000000..85cb87625 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/.parameters/parameters.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "myAlert01" + }, + "alertDescription": { + "value": "My sample Alert" + }, + "scopes": { + "value": [ + "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + ] + }, + "evaluationFrequency": { + "value": "PT5M" + }, + "windowSize": { + "value": "PT5M" + }, + "suppressForMinutes": { + "value": "PT5M" + }, + "queryTimeRange": { + "value": "PT5M" + }, + "autoMitigate": { + "value": false + }, + "criterias": { + "value": { + "allOf": [ + { + "query": "Perf | where ObjectName == \"LogicalDisk\" | where CounterName == \"% Free Space\" | where InstanceName <> \"HarddiskVolume1\" and InstanceName <> \"_Total\" | summarize AggregatedValue = min(CounterValue) by Computer, InstanceName, bin(TimeGenerated,5m)", + "timeAggregation": "Average", + "metricMeasureColumn": "AggregatedValue", + "dimensions": [ + { + "name": "Computer", + "operator": "Include", + "values": [ + "*" + ] + }, + { + "name": "InstanceName", + "operator": "Include", + "values": [ + "*" + ] + } + ], + "operator": "GreaterThan", + "threshold": 0 + } + ] + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/deploy.bicep b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/deploy.bicep new file mode 100644 index 000000000..f6c796993 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/deploy.bicep @@ -0,0 +1,126 @@ +@description('Required. The name of the Alert.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The description of the scheduled query rule.') +param alertDescription string = '' + +@description('Optional. The flag which indicates whether this scheduled query rule is enabled.') +param enabled bool = true + +@description('Optional. Indicates the type of scheduled query rule.') +@allowed([ + 'LogAlert' + 'LogToMetric' +]) +param kind string = 'LogAlert' + +@description('Optional. The flag that indicates whether the alert should be automatically resolved or not. Relevant only for rules of the kind LogAlert.') +param autoMitigate bool = true + +@description('Optional. If specified (in ISO 8601 duration format) then overrides the query time range. Relevant only for rules of the kind LogAlert.') +param queryTimeRange string = '' + +@description('Optional. The flag which indicates whether the provided query should be validated or not. Relevant only for rules of the kind LogAlert.') +param skipQueryValidation bool = false + +@description('Optional. List of resource type of the target resource(s) on which the alert is created/updated. For example if the scope is a resource group and targetResourceTypes is Microsoft.Compute/virtualMachines, then a different alert will be fired for each virtual machine in the resource group which meet the alert criteria. Relevant only for rules of the kind LogAlert') +param targetResourceTypes array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Required. The list of resource IDs that this scheduled query rule is scoped to.') +param scopes array = [] + +@description('Optional. Severity of the alert. Should be an integer between [0-4]. Value of 0 is severest. Relevant and required only for rules of the kind LogAlert.') +@allowed([ + 0 + 1 + 2 + 3 + 4 +]) +param severity int = 3 + +@description('Optional. How often the scheduled query rule is evaluated represented in ISO 8601 duration format. Relevant and required only for rules of the kind LogAlert.') +param evaluationFrequency string = '' + +@description('Optional. The period of time (in ISO 8601 duration format) on which the Alert query will be executed (bin size). Relevant and required only for rules of the kind LogAlert.') +param windowSize string = '' + +@description('Optional. Actions to invoke when the alert fires.') +param actions array = [] + +@description('Optional. The rule criteria that defines the conditions of the scheduled query rule.') +param criterias object = {} + +@description('Optional. Mute actions for the chosen period of time (in ISO 8601 duration format) after the alert is fired. If set, autoMitigate must be disabled.Relevant only for rules of the kind LogAlert.') +param suppressForMinutes string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource queryRule 'Microsoft.Insights/scheduledQueryRules@2021-02-01-preview' = { + name: name + location: location + tags: tags + kind: kind + properties: { + actions: { + actionGroups: actions + customProperties: {} + } + autoMitigate: (kind == 'LogAlert') ? autoMitigate : null + criteria: criterias + + description: alertDescription + displayName: name + enabled: enabled + evaluationFrequency: (kind == 'LogAlert' && !empty(evaluationFrequency)) ? evaluationFrequency : null + muteActionsDuration: (kind == 'LogAlert' && !empty(suppressForMinutes)) ? suppressForMinutes : null + overrideQueryTimeRange: (kind == 'LogAlert' && !empty(queryTimeRange)) ? queryTimeRange : null + scopes: scopes + severity: (kind == 'LogAlert') ? severity : null + skipQueryValidation: (kind == 'LogAlert') ? skipQueryValidation : null + targetResourceTypes: (kind == 'LogAlert') ? targetResourceTypes : null + windowSize: (kind == 'LogAlert' && !empty(windowSize)) ? windowSize : null + } +} + +module queryRule_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-QueryRule-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: queryRule.id + } +}] + +@description('The Name of the created query rule.') +output name string = queryRule.name + +@description('The resource ID of the created query rule.') +output resourceId string = queryRule.id + +@description('The Resource Group of the created query rule.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/readme.md b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/readme.md new file mode 100644 index 000000000..d43a9c3f7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/readme.md @@ -0,0 +1,103 @@ +# Scheduled Query Rules `[Microsoft.Insights/scheduledQueryRules]` + +This module deploys a scheduled query rule. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/scheduledQueryRules` | 2021-02-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Alert. | +| `scopes` | array | The list of resource IDs that this scheduled query rule is scoped to. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Actions to invoke when the alert fires. | +| `alertDescription` | string | `''` | | The description of the scheduled query rule. | +| `autoMitigate` | bool | `True` | | The flag that indicates whether the alert should be automatically resolved or not. Relevant only for rules of the kind LogAlert. | +| `criterias` | object | `{object}` | | The rule criteria that defines the conditions of the scheduled query rule. | +| `enabled` | bool | `True` | | The flag which indicates whether this scheduled query rule is enabled. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `evaluationFrequency` | string | `''` | | How often the scheduled query rule is evaluated represented in ISO 8601 duration format. Relevant and required only for rules of the kind LogAlert. | +| `kind` | string | `'LogAlert'` | `[LogAlert, LogToMetric]` | Indicates the type of scheduled query rule. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `queryTimeRange` | string | `''` | | If specified (in ISO 8601 duration format) then overrides the query time range. Relevant only for rules of the kind LogAlert. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `severity` | int | `3` | `[0, 1, 2, 3, 4]` | Severity of the alert. Should be an integer between [0-4]. Value of 0 is severest. Relevant and required only for rules of the kind LogAlert. | +| `skipQueryValidation` | bool | `False` | | The flag which indicates whether the provided query should be validated or not. Relevant only for rules of the kind LogAlert. | +| `suppressForMinutes` | string | `''` | | Mute actions for the chosen period of time (in ISO 8601 duration format) after the alert is fired. If set, autoMitigate must be disabled.Relevant only for rules of the kind LogAlert. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `targetResourceTypes` | array | `[]` | | List of resource type of the target resource(s) on which the alert is created/updated. For example if the scope is a resource group and targetResourceTypes is Microsoft.Compute/virtualMachines, then a different alert will be fired for each virtual machine in the resource group which meet the alert criteria. Relevant only for rules of the kind LogAlert | +| `windowSize` | string | `''` | | The period of time (in ISO 8601 duration format) on which the Alert query will be executed (bin size). Relevant and required only for rules of the kind LogAlert. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the created query rule. | +| `resourceGroupName` | string | The Resource Group of the created query rule. | +| `resourceId` | string | The resource ID of the created query rule. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Scheduledqueryrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-02-01-preview/scheduledQueryRules) diff --git a/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/version.json b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Insights/scheduledQueryRules/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/carml/1.0.1/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..0e3f625a3 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } +} diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c9e81020f --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Crypto Service Encryption User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') + 'Key Vault Crypto User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Key Vault Secrets User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(keyVault.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: keyVault +}] diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.KeyVault/vaults/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/.parameters/parameters.json b/carml/1.0.1/Microsoft.KeyVault/vaults/.parameters/parameters.json new file mode 100644 index 000000000..76e313e2f --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/.parameters/parameters.json @@ -0,0 +1,125 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-kv-x-001" + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "enableRbacAuthorization": { + "value": false + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "vault" + } + ] + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "secrets": { + "value": { + "secureList": [ + { + "name": "secretName", + "value": "secretValue", + "contentType": "Something", + "attributesExp": 1702648632, + "attributesNbf": 10000, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + } + }, + "keys": { + "value": [ + { + "name": "keyName", + "attributesExp": 1702648632, + "attributesNbf": 10000, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "accessPolicies": { + "value": [ + { + "objectId": "<>", + "permissions": { + "keys": [ + "get", + "list", + "update" + ], + "secrets": [ + "all" + ] + }, + "tenantId": "<>" + }, + { + "objectId": "<>", + "permissions": { + "certificates": [ + "backup", + "create", + "delete" + ], + "secrets": [ + "all" + ] + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep new file mode 100644 index 000000000..97654c373 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. The access policy deployment') +param name string = 'add' + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the access policies assignment') +output name string = policies.name + +@description('The resource ID of the access policies assignment') +output resourceId string = policies.id diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/readme.md b/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/readme.md new file mode 100644 index 000000000..f03526e8c --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/readme.md @@ -0,0 +1,68 @@ +# Key Vault Access Policies `[Microsoft.KeyVault/vaults/accessPolicies]` + +This module deploys key vault access policies. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `accessPolicies` | array | `[]` | An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'add'` | The access policy deployment | + + +### Parameter Usage: `accessPolicies` + +```json +"accessPolicies": { + "value": [ + { + "tenantId": null, // Optional + "applicationId": null, // Optional + "objectId": null, + "permissions": { + "certificates": [ + "All" + ], + "keys": [ + "All" + ], + "secrets": [ + "All" + ] + } + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the access policies assignment | +| `resourceGroupName` | string | The name of the resource group the access policies assignment was created in. | +| `resourceId` | string | The resource ID of the access policies assignment | + +## Template references + +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/version.json b/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/accessPolicies/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/carml/1.0.1/Microsoft.KeyVault/vaults/deploy.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/deploy.bicep new file mode 100644 index 000000000..fd4573981 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/deploy.bicep @@ -0,0 +1,318 @@ +// ================ // +// Parameters // +// ================ // +@description('Optional. Name of the Key Vault. If no name is provided, then unique name will be created.') +@maxLength(24) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of access policies object') +param accessPolicies array = [] + +@description('Optional. All secrets to create') +@secure() +param secrets object = {} + +@description('Optional. All keys to create') +param keys array = [] + +@description('Optional. Specifies if the vault is enabled for deployment by script or compute') +@allowed([ + true + false +]) +param enableVaultForDeployment bool = true + +@description('Optional. Specifies if the vault is enabled for a template deployment') +@allowed([ + true + false +]) +param enableVaultForTemplateDeployment bool = true + +@description('Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios.') +@allowed([ + true + false +]) +param enableVaultForDiskEncryption bool = true + +@description('Optional. Switch to enable/disable Key Vault\'s soft delete feature.') +param enableSoftDelete bool = true + +@description('Optional. softDelete data retention days. It accepts >=7 and <=90.') +param softDeleteRetentionInDays int = 90 + +@description('Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC.') +param enableRbacAuthorization bool = false + +@description('Optional. The vault\'s create mode to indicate whether the vault need to be recovered or not. - recover or default.') +param createMode string = 'default' + +@description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature.') +param enablePurgeProtection bool = false + +@description('Optional. Specifies the SKU for the vault') +@allowed([ + 'premium' + 'standard' +]) +param vaultSku string = 'premium' + +@description('Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny') +param networkAcls object = {} + +@description('Optional. Property to specify whether the vault will accept traffic from public internet. If set to "disabled" all traffic except private endpoint traffic and that that originates from trusted services will be blocked. This will override the set firewall rules, meaning that even if the firewall rules are present we will not honor the rules.') +@allowed([ + 'enabled' + 'disabled' +]) +param publicNetworkAccess string = 'enabled' + +@description('Optional. Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well') +param vNetId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AuditEvent' + 'AzurePolicyEvaluationDetails' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AuditEvent' + 'AzurePolicyEvaluationDetails' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +// =========== // +// Variables // +// =========== // +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var maxNameLength = 24 +var uniquenameUntrim = uniqueString('Key Vault${baseTime}') +var uniquename = (length(uniquenameUntrim) > maxNameLength ? substring(uniquenameUntrim, 0, maxNameLength) : uniquenameUntrim) +var name_var = !empty(name) ? name : uniquename +var virtualNetworkRules = [for networkrule in ((contains(networkAcls, 'virtualNetworkRules')) ? networkAcls.virtualNetworkRules : []): { + id: '${vNetId}/subnets/${networkrule.subnet}' +}] +var networkAcls_var = { + bypass: !empty(networkAcls) ? networkAcls.bypass : null + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: !empty(networkAcls) ? virtualNetworkRules : null + ipRules: (!empty(networkAcls) && contains(networkAcls, 'ipRules')) ? networkAcls.ipRules : [] +} + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +var secretList = !empty(secrets) ? secrets.secureList : [] + +// =========== // +// Deployments // +// =========== // +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-11-01-preview' = { + name: name_var + location: location + tags: tags + properties: { + enabledForDeployment: enableVaultForDeployment + enabledForTemplateDeployment: enableVaultForTemplateDeployment + enabledForDiskEncryption: enableVaultForDiskEncryption + enableSoftDelete: enableSoftDelete + softDeleteRetentionInDays: softDeleteRetentionInDays + enableRbacAuthorization: enableRbacAuthorization + createMode: createMode + enablePurgeProtection: enablePurgeProtection ? enablePurgeProtection : null + tenantId: subscription().tenantId + accessPolicies: formattedAccessPolicies + sku: { + name: vaultSku + family: 'A' + } + networkAcls: !empty(networkAcls) ? networkAcls_var : null + publicNetworkAccess: publicNetworkAccess + } +} + +resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${keyVault.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: keyVault +} + +resource keyVault_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: keyVault +} + +module keyVault_accessPolicies 'accessPolicies/deploy.bicep' = if (!empty(accessPolicies)) { + name: '${uniqueString(deployment().name, location)}-KeyVault-AccessPolicies' + params: { + keyVaultName: keyVault.name + accessPolicies: formattedAccessPolicies + } +} + +module keyVault_secrets 'secrets/deploy.bicep' = [for (secret, index) in secretList: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Secret-${index}' + params: { + name: secret.name + value: secret.value + keyVaultName: keyVault.name + attributesEnabled: contains(secret, 'attributesEnabled') ? secret.attributesEnabled : true + attributesExp: contains(secret, 'attributesExp') ? secret.attributesExp : -1 + attributesNbf: contains(secret, 'attributesNbf') ? secret.attributesNbf : -1 + contentType: contains(secret, 'contentType') ? secret.contentType : '' + tags: contains(secret, 'tags') ? secret.tags : {} + roleAssignments: contains(secret, 'roleAssignments') ? secret.roleAssignments : [] + } +}] + +module keyVault_keys 'keys/deploy.bicep' = [for (key, index) in keys: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Key-${index}' + params: { + name: key.name + keyVaultName: keyVault.name + attributesEnabled: contains(key, 'attributesEnabled') ? key.attributesEnabled : true + attributesExp: contains(key, 'attributesExp') ? key.attributesExp : -1 + attributesNbf: contains(key, 'attributesNbf') ? key.attributesNbf : -1 + curveName: contains(key, 'curveName') ? key.curveName : 'P-256' + keyOps: contains(key, 'keyOps') ? key.keyOps : [] + keySize: contains(key, 'keySize') ? key.keySize : -1 + kty: contains(key, 'kty') ? key.kty : 'EC' + tags: contains(key, 'tags') ? key.tags : {} + roleAssignments: contains(key, 'roleAssignments') ? key.roleAssignments : [] + } +}] + +module keyVault_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: keyVault.id + privateEndpointVnetLocation: empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module keyVault_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: keyVault.id + } +}] + +// =========== // +// Outputs // +// =========== // +@description('The resource ID of the key vault.') +output resourceId string = keyVault.id + +@description('The name of the resource group the key vault was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the key vault.') +output name string = keyVault.name + +@description('The URI of the key vault.') +output uri string = keyVault.properties.vaultUri diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..98d77676a --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Crypto Service Encryption User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') + 'Key Vault Crypto User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource key 'Microsoft.KeyVault/vaults/keys@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(key.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: key +}] diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/keys/deploy.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/deploy.bicep new file mode 100644 index 000000000..6b64e910a --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/deploy.bicep @@ -0,0 +1,109 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Required. The name of the key') +param name string + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Determines whether the object is enabled.') +param attributesEnabled bool = true + +@description('Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible.') +param attributesExp int = -1 + +@description('Optional. Not before date in seconds since 1970-01-01T00:00:00Z.') +param attributesNbf int = -1 + +@description('Optional. The elliptic curve name.') +@allowed([ + 'P-256' + 'P-256K' + 'P-384' + 'P-521' +]) +param curveName string = 'P-256' + +@description('Optional. Array of JsonWebKeyOperation') +@allowed([ + 'decrypt' + 'encrypt' + 'import' + 'sign' + 'unwrapKey' + 'verify' + 'wrapKey' +]) +param keyOps array = [] + +@description('Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA.') +param keySize int = -1 + +@description('Optional. The type of the key.') +@allowed([ + 'EC' + 'EC-HSM' + 'RSA' + 'RSA-HSM' +]) +param kty string = 'EC' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource key 'Microsoft.KeyVault/vaults/keys@2019-09-01' = { + name: name + parent: keyVault + tags: tags + properties: { + attributes: { + enabled: attributesEnabled + exp: attributesExp != -1 ? attributesExp : null + nbf: attributesNbf != -1 ? attributesNbf : null + } + curveName: curveName + keyOps: keyOps + keySize: keySize != -1 ? keySize : null + kty: kty + } +} + +module key_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: key.id + } +}] + +@description('The name of the key.') +output name string = key.name + +@description('The resource ID of the key.') +output resourceId string = key.id + +@description('The name of the resource group the key was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/keys/readme.md b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/readme.md new file mode 100644 index 000000000..a668a8dce --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/readme.md @@ -0,0 +1,96 @@ +# Key Vault Key `[Microsoft.KeyVault/vaults/keys]` + +This module deploys a key vault key. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.KeyVault/vaults/keys` | 2019-09-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault | +| `name` | string | The name of the key | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `attributesEnabled` | bool | `True` | | Determines whether the object is enabled. | +| `attributesExp` | int | `-1` | | Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible. | +| `attributesNbf` | int | `-1` | | Not before date in seconds since 1970-01-01T00:00:00Z. | +| `curveName` | string | `'P-256'` | `[P-256, P-256K, P-384, P-521]` | The elliptic curve name. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `keyOps` | array | `[]` | `[decrypt, encrypt, import, sign, unwrapKey, verify, wrapKey]` | Array of JsonWebKeyOperation | +| `keySize` | int | `-1` | | The key size in bits. For example: 2048, 3072, or 4096 for RSA. | +| `kty` | string | `'EC'` | `[EC, EC-HSM, RSA, RSA-HSM]` | The type of the key. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the key. | +| `resourceGroupName` | string | The name of the resource group the key was created in. | +| `resourceId` | string | The resource ID of the key. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/keys) diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/keys/version.json b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/keys/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/carml/1.0.1/Microsoft.KeyVault/vaults/readme.md b/carml/1.0.1/Microsoft.KeyVault/vaults/readme.md new file mode 100644 index 000000000..4729b1f6f --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/readme.md @@ -0,0 +1,216 @@ +# Key Vaults `[Microsoft.KeyVault/vaults]` + +This module deploys a key vault and its child resources. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.KeyVault/vaults` | 2021-11-01-preview | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | +| `Microsoft.KeyVault/vaults/keys` | 2019-09-01 | +| `Microsoft.KeyVault/vaults/secrets` | 2019-09-01 | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `accessPolicies` | _[accessPolicies](accessPolicies/readme.md)_ array | `[]` | | Array of access policies object | +| `createMode` | string | `'default'` | | The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogCategoriesToEnable` | array | `[AuditEvent, AzurePolicyEvaluationDetails]` | `[AuditEvent, AzurePolicyEvaluationDetails]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enablePurgeProtection` | bool | `False` | | Provide 'true' to enable Key Vault's purge protection feature. | +| `enableRbacAuthorization` | bool | `False` | | Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC. | +| `enableSoftDelete` | bool | `True` | | Switch to enable/disable Key Vault's soft delete feature. | +| `enableVaultForDeployment` | bool | `True` | `[True, False]` | Specifies if the vault is enabled for deployment by script or compute | +| `enableVaultForDiskEncryption` | bool | `True` | `[True, False]` | Specifies if the azure platform has access to the vault for enabling disk encryption scenarios. | +| `enableVaultForTemplateDeployment` | bool | `True` | `[True, False]` | Specifies if the vault is enabled for a template deployment | +| `keys` | _[keys](keys/readme.md)_ array | `[]` | | All keys to create | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `name` | string | `''` | | Name of the Key Vault. If no name is provided, then unique name will be created. | +| `networkAcls` | object | `{object}` | | Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible | +| `publicNetworkAccess` | string | `'enabled'` | `[enabled, disabled]` | Property to specify whether the vault will accept traffic from public internet. If set to "disabled" all traffic except private endpoint traffic and that that originates from trusted services will be blocked. This will override the set firewall rules, meaning that even if the firewall rules are present we will not honor the rules. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `secrets` | secureObject | `{object}` | | All secrets to create | +| `softDeleteRetentionInDays` | int | `90` | | softDelete data retention days. It accepts >=7 and <=90. | +| `tags` | object | `{object}` | | Resource tags. | +| `vaultSku` | string | `'premium'` | `[premium, standard]` | Specifies the SKU for the vault | +| `vNetId` | string | `''` | | Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a SAS token to access the modules. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "subnet": "sharedsvcs" + } + ], + "ipRules": [] + } +} +``` + +### Parameter Usage: `vNetId` + +```json +"vNetId": { + "value": "/subscriptions/00000000/resourceGroups/resourceGroup" +} +``` + +### Parameter Usage: `accessPolicies` + +```json +"accessPolicies": { + "value": [ + { + "tenantId": null, // Optional + "applicationId": null, // Optional + "objectId": null, + "permissions": { + "certificates": [ + "All" + ], + "keys": [ + "All" + ], + "secrets": [ + "All" + ] + } + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the key vault. | +| `resourceGroupName` | string | The name of the resource group the key vault was created in. | +| `resourceId` | string | The resource ID of the key vault. | +| `uri` | string | The URI of the key vault. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-11-01-preview/vaults) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) +- [Vaults/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/keys) +- [Vaults/Secrets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/secrets) diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4c12c17bd --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Key Vault Secrets User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource secret 'Microsoft.KeyVault/vaults/secrets@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(secret.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: secret +}] diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/deploy.bicep b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/deploy.bicep new file mode 100644 index 000000000..1666885b3 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/deploy.bicep @@ -0,0 +1,82 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Required. The name of the secret') +param name string + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Determines whether the object is enabled.') +param attributesEnabled bool = true + +@description('Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible.') +param attributesExp int = -1 + +@description('Optional. Not before date in seconds since 1970-01-01T00:00:00Z.') +param attributesNbf int = -1 + +@description('Optional. The content type of the secret.') +@secure() +param contentType string = '' + +@description('Required. The value of the secret. NOTE: "value" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets.') +@secure() +param value string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource secret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = { + name: name + parent: keyVault + tags: tags + properties: { + contentType: contentType + attributes: { + enabled: attributesEnabled + exp: attributesExp != -1 ? attributesExp : null + nbf: attributesNbf != -1 ? attributesNbf : null + } + value: value + } +} + +module secret_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: secret.id + } +}] + +@description('The name of the secret.') +output name string = secret.name + +@description('The resource ID of the secret.') +output resourceId string = secret.id + +@description('The name of the resource group the secret was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/readme.md b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/readme.md new file mode 100644 index 000000000..45c02db41 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/readme.md @@ -0,0 +1,94 @@ +# Key Vault Secret `[Microsoft.KeyVault/vaults/secrets]` + +This module deploys a key vault secret. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.KeyVault/vaults/secrets` | 2019-09-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault | +| `name` | string | The name of the secret | +| `value` | secureString | The value of the secret. NOTE: "value" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `attributesEnabled` | bool | `True` | Determines whether the object is enabled. | +| `attributesExp` | int | `-1` | Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible. | +| `attributesNbf` | int | `-1` | Not before date in seconds since 1970-01-01T00:00:00Z. | +| `contentType` | secureString | `''` | The content type of the secret. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | Resource tags. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the secret. | +| `resourceGroupName` | string | The name of the resource group the secret was created in. | +| `resourceId` | string | The resource ID of the secret. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Secrets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/secrets) diff --git a/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/version.json b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/secrets/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/carml/1.0.1/Microsoft.KeyVault/vaults/version.json b/carml/1.0.1/Microsoft.KeyVault/vaults/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.KeyVault/vaults/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/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/.parameters/min.parameters.json new file mode 100644 index 000000000..8beee2d23 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/.parameters/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": { + "name": { + "value": "flux" + }, + "extensionType": { + "value": "microsoft.flux" + }, + "clusterName": { + "value": "<>-az-aks-kubenet-001" + }, + "releaseTrain": { + "value": "Stable" + }, + "releaseNamespace": { + "value": "flux-system" + } + } +} diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/.parameters/parameters.json b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/.parameters/parameters.json new file mode 100644 index 000000000..29ca85067 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "flux" + }, + "extensionType": { + "value": "microsoft.flux" + }, + "clusterName": { + "value": "<>-az-aks-kubenet-001" + }, + "releaseTrain": { + "value": "Stable" + }, + "releaseNamespace": { + "value": "flux-system" + }, + "version": { + "value": "0.5.2" + }, + "configurationSettings": { + "value": { + // "helm-controller.enabled": "false", + "source-controller.enabled": "true", + "kustomize-controller.enabled": "true", + "notification-controller.enabled": "false", + "image-automation-controller.enabled": "false", + "image-reflector-controller.enabled": "false" + } + } + } +} diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/deploy.bicep b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/deploy.bicep new file mode 100644 index 000000000..df267ffaa --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/deploy.bicep @@ -0,0 +1,78 @@ +@description('Required. The name of the Flux Configuration') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. The name of the AKS cluster that should be configured.') +param clusterName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Configuration settings that are sensitive, as name-value pairs for configuring this extension.') +param configurationProtectedSettings object = {} + +@description('Optional. Configuration settings, as name-value pairs for configuring this extension.') +param configurationSettings object = {} + +@description('Required. Type of the Extension, of which this resource is an instance of. It must be one of the Extension Types registered with Microsoft.KubernetesConfiguration by the Extension publisher.') +param extensionType string + +@description('Optional. ReleaseTrain this extension participates in for auto-upgrade (e.g. Stable, Preview, etc.) - only if autoUpgradeMinorVersion is "true".') +param releaseTrain string = 'Stable' + +@description('Optional. Namespace where the extension Release must be placed, for a Cluster scoped extension. If this namespace does not exist, it will be created') +param releaseNamespace string = '' + +@description('Optional. Namespace where the extension will be created for an Namespace scoped extension. If this namespace does not exist, it will be created') +param targetNamespace string = '' + +@description('Optional. Version of the extension for this extension, if it is "pinned" to a specific version.') +param version string = '' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2021-10-01' existing = { + name: clusterName +} + +resource extension 'Microsoft.KubernetesConfiguration/extensions@2022-03-01' = { + name: name + scope: managedCluster + properties: { + autoUpgradeMinorVersion: !empty(version) ? false : true + configurationProtectedSettings: !empty(configurationProtectedSettings) ? configurationProtectedSettings : {} + configurationSettings: !empty(configurationSettings) ? configurationSettings : {} + extensionType: extensionType + releaseTrain: !empty(releaseTrain) ? releaseTrain : null + scope: { + cluster: !empty(releaseNamespace) ? { + releaseNamespace: releaseNamespace + } : null + namespace: !empty(targetNamespace) ? { + targetNamespace: targetNamespace + } : null + } + version: !empty(version) ? version : null + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The resource ID of the extension') +output resourceId string = extension.id + +@description('The name of the resource group the extension was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/readme.md b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/readme.md new file mode 100644 index 000000000..371c1b58d --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/readme.md @@ -0,0 +1,68 @@ +# Kubernetes Configuration Extensions `[Microsoft.KubernetesConfiguration/extensions]` + +This module deploys Kubernetes Configuration Extensions. + +## Navigation + +- [Prerequisites](#Prerequisites) +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Prerequisites + +Registration of your subscription with the AKS-ExtensionManager feature flag. Use the following command: + +```powershell +az feature register --namespace Microsoft.ContainerService --name AKS-ExtensionManager +``` + +Registration of the following Azure service providers. (It's OK to re-register an existing provider.) + +```powershell +az provider register --namespace Microsoft.Kubernetes +az provider register --namespace Microsoft.ContainerService +az provider register --namespace Microsoft.KubernetesConfiguration +``` + +For Details see [Prerequisites](https://docs.microsoft.com/en-us/azure/azure-arc/kubernetes/tutorial-use-gitops-flux2) +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.KubernetesConfiguration/extensions` | 2022-03-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `clusterName` | string | The name of the AKS cluster that should be configured. | +| `extensionType` | string | Type of the Extension, of which this resource is an instance of. It must be one of the Extension Types registered with Microsoft.KubernetesConfiguration by the Extension publisher. | +| `name` | string | The name of the Flux Configuration | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `configurationProtectedSettings` | object | `{object}` | Configuration settings that are sensitive, as name-value pairs for configuring this extension. | +| `configurationSettings` | object | `{object}` | Configuration settings, as name-value pairs for configuring this extension. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `releaseNamespace` | string | `''` | Namespace where the extension Release must be placed, for a Cluster scoped extension. If this namespace does not exist, it will be created | +| `releaseTrain` | string | `'Stable'` | ReleaseTrain this extension participates in for auto-upgrade (e.g. Stable, Preview, etc.) - no version must be supplied in that case. | +| `targetNamespace` | string | `''` | Namespace where the extension will be created for an Namespace scoped extension. If this namespace does not exist, it will be created | +| `version` | string | `''` | Version of the extension for this extension, if it is "pinned" to a specific version. autoUpgradeMinorVersion will be set to "false". | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the resource group the extension was deployed into | +| `resourceId` | string | The resource ID of the extension | + +## Template references + +- [Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KubernetesConfiguration/2022-03-01/extensions) diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/version.json b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/extensions/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/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/.parameters/min.parameters.json new file mode 100644 index 000000000..201ac22b6 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/.parameters/min.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": "flux2" + }, + "scope": { + "value": "cluster" + }, + "clusterName": { + "value": "<>-az-aks-kubenet-001" + }, + "namespace": { + "value": "flux-system" + }, + "sourceKind": { + "value": "GitRepository" + }, + "gitRepository": { + "value": { + "url": "https://github.com/mspnp/aks-baseline", + "timeoutInSeconds": 180, + "syncIntervalInSeconds": 300, + "repositoryRef": { + "branch": "main" + }, + "sshKnownHosts": "" + } + } + } +} diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/.parameters/parameters.json b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/.parameters/parameters.json new file mode 100644 index 000000000..e6f563f7f --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/.parameters/parameters.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "flux2" + }, + "scope": { + "value": "cluster" + }, + "clusterName": { + "value": "<>-az-aks-kubenet-001" + }, + "namespace": { + "value": "flux-system" + }, + "sourceKind": { + "value": "GitRepository" + }, + "gitRepository": { + "value": { + "url": "https://github.com/mspnp/aks-baseline", + "timeoutInSeconds": 180, + "syncIntervalInSeconds": 300, + "repositoryRef": { + "branch": "main" + }, + "sshKnownHosts": "" + } + }, + "kustomizations": { + "value": { + "unified": { + "path": "./cluster-manifests", + "dependsOn": [], + "timeoutInSeconds": 300, + "syncIntervalInSeconds": 300, + "prune": true, + "force": false + } + } + } + } +} diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/deploy.bicep b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/deploy.bicep new file mode 100644 index 000000000..3a1982cc7 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/deploy.bicep @@ -0,0 +1,83 @@ +@description('Required. The name of the Flux Configuration') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. The name of the AKS cluster that should be configured.') +param clusterName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Parameters to reconcile to the GitRepository source kind type.') +param bucket object = {} + +@description('Optional. Key-value pairs of protected configuration settings for the configuration') +param configurationProtectedSettings object = {} + +@description('Optional. Parameters to reconcile to the GitRepository source kind type.') +param gitRepository object = {} + +@description('Optional. Array of kustomizations used to reconcile the artifact pulled by the source type on the cluster.') +param kustomizations object = {} + +@description('Required. The namespace to which this configuration is installed to. Maximum of 253 lower case alphanumeric characters, hyphen and period only.') +param namespace string + +@allowed([ + 'cluster' + 'namespace' +]) +@description('Required. Scope at which the configuration will be installed.') +param scope string + +@allowed([ + 'Bucket' + 'GitRepository' +]) +@description('Required. Source Kind to pull the configuration data from.') +param sourceKind string + +@description('Optional. Whether this configuration should suspend its reconciliation of its kustomizations and sources.') +param suspend bool = false + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedCluster 'Microsoft.ContainerService/managedClusters@2021-10-01' existing = { + name: clusterName +} + +resource fluxConfiguration 'Microsoft.KubernetesConfiguration/fluxConfigurations@2022-03-01' = { + name: name + scope: managedCluster + properties: { + bucket: !empty(bucket) ? bucket : null + configurationProtectedSettings: !empty(configurationProtectedSettings) ? configurationProtectedSettings : {} + gitRepository: !empty(gitRepository) ? gitRepository : null + kustomizations: !empty(kustomizations) ? kustomizations : {} + namespace: namespace + scope: scope + sourceKind: sourceKind + suspend: suspend + } +} + +@description('The name of the flux configuration') +output name string = fluxConfiguration.name + +@description('The resource ID of the flux configuration') +output resourceId string = fluxConfiguration.id + +@description('The name of the resource group the flux configuration was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/readme.md b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/readme.md new file mode 100644 index 000000000..5e998c8a6 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/readme.md @@ -0,0 +1,108 @@ +# Kubernetes Configuration Flux Configurations `[Microsoft.KubernetesConfiguration/fluxConfigurations]` + +This module deploys Kubernetes Configuration Flux Configurations. + +## Navigation + +- [Prerequisites](#Prerequisites) +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Prerequisites + +Registration of your subscription with the AKS-ExtensionManager feature flag. Use the following command: + +```powershell +az feature register --namespace Microsoft.ContainerService --name AKS-ExtensionManager +``` + +Registration of the following Azure service providers. (It's OK to re-register an existing provider.) + +```powershell +az provider register --namespace Microsoft.Kubernetes +az provider register --namespace Microsoft.ContainerService +az provider register --namespace Microsoft.KubernetesConfiguration +``` + +For Details see [Prerequisites](https://docs.microsoft.com/en-us/azure/azure-arc/kubernetes/tutorial-use-gitops-flux2) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.KubernetesConfiguration/fluxConfigurations` | 2022-03-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `clusterName` | string | | The name of the AKS cluster that should be configured. | +| `name` | string | | The name of the Flux Configuration | +| `namespace` | string | | The namespace to which this configuration is installed to. Maximum of 253 lower case alphanumeric characters, hyphen and period only. | +| `scope` | string | `[cluster, namespace]` | Scope at which the configuration will be installed. | +| `sourceKind` | string | `[Bucket, GitRepository]` | Source Kind to pull the configuration data from. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `bucket` | object | `{object}` | Parameters to reconcile to the GitRepository source kind type. | +| `configurationProtectedSettings` | object | `{object}` | Key-value pairs of protected configuration settings for the configuration | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `gitRepository` | object | `{object}` | Parameters to reconcile to the GitRepository source kind type. | +| `kustomizations` | object | `{object}` | Array of kustomizations used to reconcile the artifact pulled by the source type on the cluster. | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `suspend` | bool | `False` | Whether this configuration should suspend its reconciliation of its kustomizations and sources. | + + +### Parameter Usage: `bucket` + +```json +"bucket": { + "value": { + "accessKey": "string", + "bucketName": "string", + "insecure": "bool", + "localAuthRef": "string", + "syncIntervalInSeconds": "int", + "timeoutInSeconds": "int", + "url": "string" + } +} +``` + +### Parameter Usage: `gitRepository` + +```json +"gitRepository": { + "value": { + "httpsCACert": "string", + "httpsUser": "string", + "localAuthRef": "string", + "repositoryRef": { + "branch": "string", + "commit": "string", + "semver": "string", + "tag": "string" + }, + "sshKnownHosts": "string", + "syncIntervalInSeconds": "int", + "timeoutInSeconds": "int", + "url": "string" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the flux configuration | +| `resourceGroupName` | string | The name of the resource group the flux configuration was deployed into | +| `resourceId` | string | The resource ID of the flux configuration | + +## Template references + +- [Fluxconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KubernetesConfiguration/2022-03-01/fluxConfigurations) diff --git a/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/version.json b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.KubernetesConfiguration/fluxConfigurations/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/carml/1.0.1/Microsoft.Logic/workflows/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Logic/workflows/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d320ae3ac --- /dev/null +++ b/carml/1.0.1/Microsoft.Logic/workflows/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Sentinel Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4c81013-99ee-4d62-a7ee-b3f1f648599a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource logicApp 'Microsoft.Logic/workflows@2019-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(logicApp.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: logicApp +}] diff --git a/carml/1.0.1/Microsoft.Logic/workflows/.parameters/parameters.json b/carml/1.0.1/Microsoft.Logic/workflows/.parameters/parameters.json new file mode 100644 index 000000000..7ead1ba4b --- /dev/null +++ b/carml/1.0.1/Microsoft.Logic/workflows/.parameters/parameters.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lga-x-001" + }, + "tags": { + "value": {} + }, + "workflowActions": { + "value": { + "HTTP": { + "type": "Http", + "inputs": { + "method": "POST", + "uri": "https://testStringForValidation.com", + "body": { + "HostPoolName": "[HostPoolName]", + "LAWorkspaceName": "[LAWorkspaceName]", + "LimitSecondsToForceLogOffUser": "[LimitSecondsToForceLogOffUser]", + "EndPeakTime": "[EndPeakTime]", + "BeginPeakTime": "[BeginPeakTime]", + "UtcOffset": "[UtcOffset]", + "LogOffMessageBody": "[LogOffMessageBody]", + "LogOffMessageTitle": "[LogOffMessageTitle]", + "MinimumNumberOfRDSH": 1, + "SessionThresholdPerCPU": 1, + "ResourceGroupName": "[ResourceGroupName]" + } + } + } + } + }, + "workflowTriggers": { + "value": { + "Recurrence": { + "recurrence": { + "frequency": "Minute", + "interval": 15 + }, + "type": "Recurrence" + } + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.1/Microsoft.Logic/workflows/deploy.bicep b/carml/1.0.1/Microsoft.Logic/workflows/deploy.bicep new file mode 100644 index 000000000..14407d7b5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Logic/workflows/deploy.bicep @@ -0,0 +1,236 @@ +@description('Required. The logic app workflow name.') +param name string + +@description('Optional. The access control configuration for workflow actions.') +param actionsAccessControlConfiguration object = {} + +@description('Optional. The endpoints configuration: Access endpoint and outgoing IP addresses for the connector.') +param connectorEndpointsConfiguration object = {} + +@description('Optional. The access control configuration for accessing workflow run contents.') +param contentsAccessControlConfiguration object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Parameters for the definition template.') +param definitionParameters object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The integration account.') +param integrationAccount object = {} + +@description('Optional. The integration service environment.') +param integrationServiceEnvironment object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Sku of Logic App. Only to be set when integrating with ISE.') +param sku object = {} + +@description('Optional. The state. - NotSpecified, Completed, Enabled, Disabled, Deleted, Suspended.') +@allowed([ + 'NotSpecified' + 'Completed' + 'Enabled' + 'Disabled' + 'Deleted' + 'Suspended' +]) +param state string = 'Enabled' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The access control configuration for invoking workflow triggers.') +param triggersAccessControlConfiguration object = {} + +@description('Optional. The definitions for one or more actions to execute at workflow runtime.') +param workflowActions object = {} + +@description('Optional. The endpoints configuration: Access endpoint and outgoing IP addresses for the workflow.') +param workflowEndpointsConfiguration object = {} + +@description('Optional. The access control configuration for workflow management.') +param workflowManagementAccessControlConfiguration object = {} + +@description('Optional. The definitions for the outputs to return from a workflow run.') +param workflowOutputs object = {} + +@description('Optional. The definitions for one or more parameters that pass the values to use at your logic app\'s runtime.') +param workflowParameters object = {} + +@description('Optional. The definitions for one or more static results returned by actions as mock outputs when static results are enabled on those actions. In each action definition, the runtimeConfiguration.staticResult.name attribute references the corresponding definition inside staticResults.') +param workflowStaticResults object = {} + +@description('Optional. The definitions for one or more triggers that instantiate your workflow. You can define more than one trigger, but only with the Workflow Definition Language, not visually through the Logic Apps Designer.') +param workflowTriggers object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'WorkflowRuntime' +]) +param diagnosticLogCategoriesToEnable array = [ + 'WorkflowRuntime' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? 'SystemAssigned' : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource logicApp 'Microsoft.Logic/workflows@2019-05-01' = { + name: name + location: location + tags: !empty(tags) ? tags : null + identity: identity + properties: { + state: state + endpointsConfiguration: { + workflow: workflowEndpointsConfiguration + connector: connectorEndpointsConfiguration + } + sku: !empty(sku) ? sku : null + accessControl: { + triggers: !empty(triggersAccessControlConfiguration) ? triggersAccessControlConfiguration : null + contents: !empty(contentsAccessControlConfiguration) ? contentsAccessControlConfiguration : null + actions: !empty(actionsAccessControlConfiguration) ? actionsAccessControlConfiguration : null + workflowManagement: !empty(workflowManagementAccessControlConfiguration) ? workflowManagementAccessControlConfiguration : null + } + integrationAccount: !empty(integrationAccount) ? integrationAccount : null + integrationServiceEnvironment: !empty(integrationServiceEnvironment) ? integrationServiceEnvironment : null + definition: { + '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#' + actions: workflowActions + contentVersion: '1.0.0.0' + outputs: workflowOutputs + parameters: workflowParameters + staticResults: workflowStaticResults + triggers: workflowTriggers + } + parameters: definitionParameters + } +} + +resource logicApp_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${logicApp.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: logicApp +} + +resource logicApp_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: logicApp +} + +module logicApp_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LogicApp-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: logicApp.id + } +}] + +@description('The name of the logic app') +output name string = logicApp.name + +@description('The resource group the logic app was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the logic app') +output resourceId string = logicApp.id + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(logicApp.identity, 'principalId') ? logicApp.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Logic/workflows/readme.md b/carml/1.0.1/Microsoft.Logic/workflows/readme.md new file mode 100644 index 000000000..67a7d722f --- /dev/null +++ b/carml/1.0.1/Microsoft.Logic/workflows/readme.md @@ -0,0 +1,186 @@ +# Logic Apps `[Microsoft.Logic/workflows]` + +This module deploys a Logic App resource. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Logic/workflows` | 2019-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The logic app workflow name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actionsAccessControlConfiguration` | object | `{object}` | | The access control configuration for workflow actions. | +| `connectorEndpointsConfiguration` | object | `{object}` | | The endpoints configuration: Access endpoint and outgoing IP addresses for the connector. | +| `contentsAccessControlConfiguration` | object | `{object}` | | The access control configuration for accessing workflow run contents. | +| `definitionParameters` | object | `{object}` | | Parameters for the definition template. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[WorkflowRuntime]` | `[WorkflowRuntime]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `integrationAccount` | object | `{object}` | | The integration account. | +| `integrationServiceEnvironment` | object | `{object}` | | The integration service environment. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `sku` | object | `{object}` | | Sku of Logic App. Only to be set when integrating with ISE. | +| `state` | string | `'Enabled'` | `[NotSpecified, Completed, Enabled, Disabled, Deleted, Suspended]` | The state. - NotSpecified, Completed, Enabled, Disabled, Deleted, Suspended. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `triggersAccessControlConfiguration` | object | `{object}` | | The access control configuration for invoking workflow triggers. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `workflowActions` | object | `{object}` | | The definitions for one or more actions to execute at workflow runtime. | +| `workflowEndpointsConfiguration` | object | `{object}` | | The endpoints configuration: Access endpoint and outgoing IP addresses for the workflow. | +| `workflowManagementAccessControlConfiguration` | object | `{object}` | | The access control configuration for workflow management. | +| `workflowOutputs` | object | `{object}` | | The definitions for the outputs to return from a workflow run. | +| `workflowParameters` | object | `{object}` | | The definitions for one or more parameters that pass the values to use at your logic app's runtime. | +| `workflowStaticResults` | object | `{object}` | | The definitions for one or more static results returned by actions as mock outputs when static results are enabled on those actions. In each action definition, the runtimeConfiguration.staticResult.name attribute references the corresponding definition inside staticResults. | +| `workflowTriggers` | object | `{object}` | | The definitions for one or more triggers that instantiate your workflow. You can define more than one trigger, but only with the Workflow Definition Language, not visually through the Logic Apps Designer. | + + +### Parameter Usage `AccessControlConfiguration` + +- `actionsAccessControlConfiguration` +- `contentsAccessControlConfiguration` +- `triggersAccessControlConfiguration` +- `workflowManagementAccessControlConfiguration` + +```json +"AccessControlConfiguration": { + "value": { + "allowedCallerIpAddresses": [ + { + "addressRange": "string" + } + ], + "openAuthenticationPolicies": { +"policies": {} + } + } +} +``` + +### Parameter Usage `EndpointsConfiguration` + +- `connectorEndpointsConfiguration` +- `workflowEndpointsConfiguration` + +```json +"EndpointsConfiguration": { + "value": { + "outgoingIpAddresses": [ + { + "address": "string" + } + ], + "accessEndpointIpAddresses": [ + { + "address": "string" + } + ] +} +``` + +### Parameter Usage `workflow*` + +- To use the below parameters, see the following [documentation.](https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-workflow-definition-language) + - `workflowActions` + - `workflowOutputs` + - `workflowParameters` + - `workflowStaticResults` + - `workflowTriggers` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the logic app | +| `resourceGroupName` | string | The resource group the logic app was deployed into | +| `resourceId` | string | The resource ID of the logic app | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workflows](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Logic/2019-05-01/workflows) diff --git a/carml/1.0.1/Microsoft.Logic/workflows/version.json b/carml/1.0.1/Microsoft.Logic/workflows/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Logic/workflows/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/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..82ab478cd --- /dev/null +++ b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..635474e90 --- /dev/null +++ b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,54 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'AzureML Metrics Writer (preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '635dd51f-9968-44d3-b7fb-6d9a6bd613ae') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.MachineLearningServices/workspaces@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: workspace +}] diff --git a/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.parameters/parameters.json b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..82dc8e870 --- /dev/null +++ b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-mls-x-001" + }, + "sku": { + "value": "Basic" + }, + "associatedStorageAccountResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "associatedKeyVaultResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "associatedApplicationInsightsResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + } + } +} diff --git a/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/deploy.bicep b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/deploy.bicep new file mode 100644 index 000000000..e3aea7f9e --- /dev/null +++ b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/deploy.bicep @@ -0,0 +1,209 @@ +@description('Required. The name of the machine learning workspace.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Specifies the sku, also referred as \'edition\' of the Azure Machine Learning workspace.') +@allowed([ + 'Basic' + 'Enterprise' +]) +param sku string + +@description('Required. The resource ID of the associated Storage Account.') +param associatedStorageAccountResourceId string + +@description('Required. The resource ID of the associated Key Vault.') +param associatedKeyVaultResourceId string + +@description('Required. The resource ID of the associated Application Insights.') +param associatedApplicationInsightsResourceId string + +@description('Optional. The resource ID of the associated Container Registry.') +param associatedContainerRegistryResourceId string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The flag to signal HBI data in the workspace and reduce diagnostic data collected by the service.') +param hbiWorkspace bool = false + +@description('Optional. The flag to indicate whether to allow public access when behind VNet.') +param allowPublicAccessWhenBehindVnet bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AmlComputeClusterEvent' + 'AmlComputeClusterNodeEvent' + 'AmlComputeJobEvent' + 'AmlComputeCpuGpuUtilization' + 'AmlRunStatusChangedEvent' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AmlComputeClusterEvent' + 'AmlComputeClusterNodeEvent' + 'AmlComputeJobEvent' + 'AmlComputeCpuGpuUtilization' + 'AmlRunStatusChangedEvent' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? 'SystemAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.MachineLearningServices/workspaces@2021-04-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + tier: sku + } + identity: identity + properties: { + friendlyName: name + storageAccount: associatedStorageAccountResourceId + keyVault: associatedKeyVaultResourceId + applicationInsights: associatedApplicationInsightsResourceId + containerRegistry: ((!(associatedContainerRegistryResourceId == '')) ? associatedContainerRegistryResourceId : null) + hbiWorkspace: hbiWorkspace + allowPublicAccessWhenBehindVnet: allowPublicAccessWhenBehindVnet + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-MLWorkspace-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: workspace.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-MLWorkspace-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The resource ID of the machine learning service') +output resourceId string = workspace.id + +@description('The resource group the machine learning service was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the machine learning service') +output name string = workspace.name + +@description('The principal ID of the system assigned identity.') +output principalId string = systemAssignedIdentity ? workspace.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/readme.md b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/readme.md new file mode 100644 index 000000000..6b12b5366 --- /dev/null +++ b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/readme.md @@ -0,0 +1,152 @@ +# Machine Learning Workspaces `[Microsoft.MachineLearningServices/workspaces]` + +This module deploys a Machine Learning Services Workspace. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.MachineLearningServices/workspaces` | 2021-04-01 | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `associatedApplicationInsightsResourceId` | string | | The resource ID of the associated Application Insights. | +| `associatedKeyVaultResourceId` | string | | The resource ID of the associated Key Vault. | +| `associatedStorageAccountResourceId` | string | | The resource ID of the associated Storage Account. | +| `name` | string | | The name of the machine learning workspace. | +| `sku` | string | `[Basic, Enterprise]` | Specifies the sku, also referred as 'edition' of the Azure Machine Learning workspace. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowPublicAccessWhenBehindVnet` | bool | `False` | | The flag to indicate whether to allow public access when behind VNet. | +| `associatedContainerRegistryResourceId` | string | `''` | | The resource ID of the associated Container Registry. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[AmlComputeClusterEvent, AmlComputeClusterNodeEvent, AmlComputeJobEvent, AmlComputeCpuGpuUtilization, AmlRunStatusChangedEvent]` | `[AmlComputeClusterEvent, AmlComputeClusterNodeEvent, AmlComputeJobEvent, AmlComputeCpuGpuUtilization, AmlRunStatusChangedEvent]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hbiWorkspace` | bool | `False` | | The flag to signal HBI data in the workspace and reduce diagnostic data collected by the service. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the machine learning service | +| `principalId` | string | The principal ID of the system assigned identity. | +| `resourceGroupName` | string | The resource group the machine learning service was deployed into | +| `resourceId` | string | The resource ID of the machine learning service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.MachineLearningServices/2021-04-01/workspaces) diff --git a/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/version.json b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.MachineLearningServices/workspaces/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/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..cbb3862c2 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource userMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(userMsi.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: userMsi +}] diff --git a/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json new file mode 100644 index 000000000..141d57730 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-msi-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep new file mode 100644 index 000000000..204da36b7 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep @@ -0,0 +1,72 @@ +@description('Optional. Name of the User Assigned Identity.') +param name string = guid(resourceGroup().id) + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource userMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: name + location: location + tags: tags +} + +resource userMsi_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${userMsi.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: userMsi +} + +module userMsi_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-UserMSI-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: userMsi.id + } +}] + +@description('The name of the user assigned identity') +output name string = userMsi.name + +@description('The resource ID of the user assigned identity') +output resourceId string = userMsi.id + +@description('The principal ID of the user assigned identity') +output principalId string = userMsi.properties.principalId + +@description('The resource group the user assigned identity was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md new file mode 100644 index 000000000..dffc0d77a --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md @@ -0,0 +1,89 @@ +# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` + +This module deploys a user assigned identity. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ManagedIdentity/userAssignedIdentities` | 2018-11-30 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `name` | string | `[guid(resourceGroup().id)]` | | Name of the User Assigned Identity. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the user assigned identity | +| `principalId` | string | The principal ID of the user assigned identity | +| `resourceGroupName` | string | The resource group the user assigned identity was deployed into | +| `resourceId` | string | The resource ID of the user assigned identity | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Userassignedidentities](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2018-11-30/userAssignedIdentities) diff --git a/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/version.json b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedIdentity/userAssignedIdentities/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/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.bicep/nested_registrationAssignment.bicep b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.bicep/nested_registrationAssignment.bicep new file mode 100644 index 000000000..7bfca49e9 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.bicep/nested_registrationAssignment.bicep @@ -0,0 +1,15 @@ +param registrationDefinitionId string +param registrationAssignmentId string + +resource registrationAssignment 'Microsoft.ManagedServices/registrationAssignments@2019-09-01' = { + name: registrationAssignmentId + properties: { + registrationDefinitionId: registrationDefinitionId + } +} + +@description('The name of the registration assignment') +output name string = registrationAssignment.name + +@description('The resource ID of the registration assignment') +output resourceId string = registrationAssignment.id diff --git a/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.parameters/parameters.json b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.parameters/parameters.json new file mode 100644 index 000000000..8fc6fc1cc --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.parameters/parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "Component Validation - Subscription assignment" + }, + "registrationDescription": { + "value": "Managed by Lighthouse" + }, + "managedByTenantId": { + "value": "195ee85d-2f10-4764-8352-a3c99aa772fb" + }, + "authorizations": { + "value": [ + { + "principalId": "e87a249c-b53b-4685-94fe-863af522e4ee", + "principalIdDisplayName": "ResourceModules-Reader", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + }, + { + "principalId": "e2f126a7-136e-443f-b39f-f73ddfd146b1", + "principalIdDisplayName": "ResourceModules-Contributor", + "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "87813317-fb25-4c76-91fe-783af429d109", + "principalIdDisplayName": "ResourceModules-LHManagement", + "roleDefinitionId": "91c1777a-f3dc-4fae-b103-61d183457e46" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.parameters/rg.parameters.json b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.parameters/rg.parameters.json new file mode 100644 index 000000000..5e2141436 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/.parameters/rg.parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "Component Validation - Resource group assignment" + }, + "registrationDescription": { + "value": "Managed by Lighthouse" + }, + "managedByTenantId": { + "value": "195ee85d-2f10-4764-8352-a3c99aa772fb" + }, + "resourceGroupName": { + "value": "validation-rg" + }, + "authorizations": { + "value": [ + { + "principalId": "e87a249c-b53b-4685-94fe-863af522e4ee", + "principalIdDisplayName": "ResourceModules-Reader", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + }, + { + "principalId": "e2f126a7-136e-443f-b39f-f73ddfd146b1", + "principalIdDisplayName": "ResourceModules-Contributor", + "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "87813317-fb25-4c76-91fe-783af429d109", + "principalIdDisplayName": "ResourceModules-LHManagement", + "roleDefinitionId": "91c1777a-f3dc-4fae-b103-61d183457e46" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/deploy.bicep b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/deploy.bicep new file mode 100644 index 000000000..6f8252e92 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'subscription' + +@description('Required. Specify a unique name for your offer/registration. i.e \' - - \'') +param name string + +@description('Required. Description of the offer/registration. i.e. \'Managed by \'') +param registrationDescription string + +@description('Required. Specify the tenant ID of the tenant which homes the principals you are delegating permissions to.') +param managedByTenantId string + +@description('Required. Specify an array of objects, containing object of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider\'s Active Directory and the principalIdDisplayName is visible to customers.') +param authorizations array + +@description('Optional. Specify the name of the Resource Group to delegate access to. If not provided, delegation will be done on the targeted subscription.') +param resourceGroupName string = '' + +@description('Optional. Location deployment metadata.') +param location string = deployment().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var registrationId = empty(resourceGroupName) ? guid(managedByTenantId, subscription().tenantId, subscription().subscriptionId) : guid(managedByTenantId, subscription().tenantId, subscription().subscriptionId, resourceGroupName) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource registrationDefinition 'Microsoft.ManagedServices/registrationDefinitions@2019-09-01' = { + name: registrationId + properties: { + registrationDefinitionName: name + description: registrationDescription + managedByTenantId: managedByTenantId + authorizations: authorizations + } +} + +resource registrationAssignment_sub 'Microsoft.ManagedServices/registrationAssignments@2019-09-01' = if (empty(resourceGroupName)) { + name: registrationId + properties: { + registrationDefinitionId: registrationDefinition.id + } +} + +module registrationAssignment_rg '.bicep/nested_registrationAssignment.bicep' = if (!empty(resourceGroupName)) { + name: '${uniqueString(deployment().name)}-RegDef-RegAssignment' + scope: resourceGroup(resourceGroupName) + params: { + registrationDefinitionId: registrationDefinition.id + registrationAssignmentId: registrationId + } +} + +@description('The name of the registration definition') +output name string = registrationDefinition.name + +@description('The resource ID of the registration definition') +output resourceId string = registrationDefinition.id + +@description('The subscription the registration definition was deployed into') +output subscriptionName string = subscription().displayName + +@description('The registration assignment resource ID') +output assignmentResourceId string = empty(resourceGroupName) ? registrationAssignment_sub.id : registrationAssignment_rg.outputs.resourceId diff --git a/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/readme.md b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/readme.md new file mode 100644 index 000000000..2971aeb02 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/readme.md @@ -0,0 +1,138 @@ +# Registration Definitions `[Microsoft.ManagedServices/registrationDefinitions]` + +This module deploys `registrationDefinitions` and `registrationAssignments` (often refered to as 'Lighthouse' or 'resource delegation') +on subscription or resource group scopes. This type of delegation is very similar to role assignments but here the principal that is +assigned a role is in a remote/managing Azure Active Directory tenant. The templates are run towards the tenant where +the Azure resources you want to delegate access to are, providing 'authorizations' (aka. access delegation) to principals in a +remote/managing tenant. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ManagedServices/registrationAssignments` | 2019-09-01 | +| `Microsoft.ManagedServices/registrationDefinitions` | 2019-09-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `authorizations` | array | Specify an array of objects, containing object of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider's Active Directory and the principalIdDisplayName is visible to customers. | +| `managedByTenantId` | string | Specify the tenant ID of the tenant which homes the principals you are delegating permissions to. | +| `name` | string | Specify a unique name for your offer/registration. i.e ' - - ' | +| `registrationDescription` | string | Description of the offer/registration. i.e. 'Managed by ' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `resourceGroupName` | string | `''` | Specify the name of the Resource Group to delegate access to. If not provided, delegation will be done on the targeted subscription. | + + +### Parameter Usage: `authorizations` + +| Parameter Name | Type | Default Value | Possible values | Description | +| :----------------------- | :----- | :------------ | :-------------- | :------------------------------------------------------------------------------------------ | +| `principalId` | string | | GUID | Required. The object ID of the principal in the managing tenant to delegate permissions to. | +| `principalIdDisplayName` | string | `principalId` | | Optional. A display name of the principal that is delegated permissions to. | +| `roleDefinitionId` | string | | GUID | Required. The role definition ID to delegate to the principal in the managing tenant. | + +```json +"authorizations": { + "value": [ + // Delegates 'Reader' to a group in managing tenant (managedByTenantId) + { + "principalId": "9d949eef-00d5-45d9-8586-56be91a13398", + "principalIdDisplayName": "Reader-Group", + "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7" + }, + // Delegates 'Contributor' to a group in managing tenant (managedByTenantId) + { + "principalId": "06eb144f-1a10-4935-881b-757efd1d0b58", + "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + // Delegates 'Managed Services Registration assignment Delete Role' to a group in managing tenant (managedByTenantId) + { + "principalId": "9cd792b0-dc7c-4551-84f8-dd87388030fb", + "principalIdDisplayName": "LighthouseManagement-Group", + "roleDefinitionId": "91c1777a-f3dc-4fae-b103-61d183457e46" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `assignmentResourceId` | string | The registration assignment resource ID | +| `name` | string | The name of the registration definition | +| `resourceId` | string | The resource ID of the registration definition | +| `subscriptionName` | string | The subscription the registration definition was deployed into | + +## Considerations + +This module can be deployed both at subscription and resource group level: + +- To deploy the module at resource group level, provide a valid name of an existing Resource Group in the `resourceGroupName` parameter. +- To deploy the module at the subscription level, leave the `resourceGroupName` parameter empty. + +### Permissions required to create delegations + +This deployment must be done by a non-guest account in the customer's tenant which has a role with the `Microsoft.Authorization/roleAssignments/write` permission, +such as [`Owner`](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#owner) for the subscription being onboarded (or which contains the resource groups that are being onboarded). + +If the subscription was created through the Cloud Solution Provider (CSP) program, any user who has the AdminAgent role in your service provider tenant can perform the deployment. + +**More info on this topic:** + +- [Deploy the Azure Resource Manager templates - Onboard a customer to Azure Lighthouse | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer#deploy-the-azure-resource-manager-templates) + +### Permissions required to remove delegations + +#### From customer side + +Users in the customer's tenant who have a role with the `Microsoft.Authorization/roleAssignments/write` permission, such as +[`Owner`](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#owner) can remove service provider +access to that subscription (or to resource groups in that subscription). To do so, the user can go to the Service providers +page of the Azure portal and delete the delegation. + +#### From managing tenant side + +Users in a managing tenant can remove access to delegated resources if they were granted the +[`Managed Services Registration Assignment Delete Role`](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#managed-services-registration-assignment-delete-role) +for the customer's resources. If this role was not assigned to any service provider users, the delegation can **only** be +removed by a user in the customer's tenant. + +**More info on this topic:** + +- [Service providers - Remove access to a delegation | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/how-to/remove-delegation#service-providers) + +### Limitations with Lighthouse and resource delegation + +There are a couple of limitations that you should be aware of with Lighthouse: + +- Only allows resource delegation within Azure Resource Manager. Excludes Azure Active Directory, Microsoft 365 and Dynamics 365. +- Only supports delegation of control plane permissions. Excludes data plane access. +- Only supports subscription and resource group scopes. Excludes tenant and management group delegations. +- Only supports built-in roles, with the exception of `Owner`. Excludes the use of custom roles. + +**More info on this topic:** + +- [Current limitations - Cross-tenant management experiences | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/concepts/cross-tenant-management-experience#current-limitations) +- [Troubleshooting - Onboard a customer to Azure Lighthouse | Microsoft Docs](https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer#troubleshooting) + +## Template references + +- [Registrationassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ManagedServices/2019-09-01/registrationAssignments) +- [Registrationdefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ManagedServices/2019-09-01/registrationDefinitions) diff --git a/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/version.json b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ManagedServices/registrationDefinitions/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/carml/1.0.1/Microsoft.Management/managementGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Management/managementGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4e9b810ff --- /dev/null +++ b/carml/1.0.1/Microsoft.Management/managementGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,318 @@ +targetScope = 'managementGroup' + +@sys.description('Required. The IDs of the principals to assign the role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'AcrPush': '/providers/Microsoft.Authorization/roleDefinitions/8311e382-0749-4cb8-b61a-304f252e45ec' + 'API Management Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/312a565d-c81f-4fd8-895a-4e21e48d571c' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(last(split(resourceId, '/')), principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } +}] diff --git a/carml/1.0.1/Microsoft.Management/managementGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Management/managementGroups/.parameters/parameters.json new file mode 100644 index 000000000..2ecb3b947 --- /dev/null +++ b/carml/1.0.1/Microsoft.Management/managementGroups/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "testMG" + }, + "displayName": { + "value": "Test MG" + }, + "parentId": { + "value": "<>" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Management/managementGroups/deploy.bicep b/carml/1.0.1/Microsoft.Management/managementGroups/deploy.bicep new file mode 100644 index 000000000..7e5a3ecc4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Management/managementGroups/deploy.bicep @@ -0,0 +1,63 @@ +targetScope = 'managementGroup' + +@description('Required. The group ID of the Management group') +param name string + +@description('Optional. The friendly name of the management group. If no value is passed then this field will be set to the group ID.') +param displayName string = '' + +@description('Optional. The management group parent ID. Defaults to current scope.') +param parentId string = '' + +@description('Optional. Array of role assignment objects to define RBAC on this resource.') +param roleAssignments array = [] + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managementGroup 'Microsoft.Management/managementGroups@2021-04-01' = { + name: name + scope: tenant() + properties: { + displayName: displayName + details: !empty(parentId) ? { + parent: { + id: '/providers/Microsoft.Management/managementGroups/${parentId}' + } + } : null + } +} + +module managementGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name)}-ManagementGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: managementGroup.id + } + scope: managementGroup +}] + +@description('The name of the management group') +output name string = managementGroup.name + +@description('The resource ID of the management group') +output resourceId string = managementGroup.id diff --git a/carml/1.0.1/Microsoft.Management/managementGroups/readme.md b/carml/1.0.1/Microsoft.Management/managementGroups/readme.md new file mode 100644 index 000000000..c6e0a1cff --- /dev/null +++ b/carml/1.0.1/Microsoft.Management/managementGroups/readme.md @@ -0,0 +1,96 @@ +# Management Groups `[Microsoft.Management/managementGroups]` + +This template will prepare the management group structure based on the provided parameter. + +This module has some known **limitations**: + +- It's not possible to change the display name of the root management group (the one that has the tenant GUID as ID) +- It can't manage the Root (/) management group + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Management/managementGroups` | 2021-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The group ID of the Management group | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `displayName` | string | `''` | The friendly name of the management group. If no value is passed then this field will be set to the group ID. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `parentId` | string | `''` | The management group parent ID. Defaults to current scope. | +| `roleAssignments` | array | `[]` | Array of role assignment objects to define RBAC on this resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the management group | +| `resourceId` | string | The resource ID of the management group | + +## Considerations + +This template is using a **Tenant level deployment**, meaning the user/principal deploying it needs to have the [proper access](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/deploy-to-tenant#required-access) + +If owner access is excessive, the following rights roles will grant enough rights: + +- **Automation Job Operator** at **tenant** level (scope '/') +- **Management Group Contributor** at the top management group that needs to be managed + +Consider using the following script: + +```powershell +$PrincipalID = "" +$TopMGID = "" +New-AzRoleAssignment -ObjectId $PrincipalID -Scope "/" -RoleDefinitionName "Automation Job Operator" +New-AzRoleAssignment -ObjectId $PrincipalID -Scope "/providers/Microsoft.Management/managementGroups/$TopMGID" -RoleDefinitionName "Management Group Contributor" +``` + +## Template references + +- [Managementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Management/2021-04-01/managementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Management/managementGroups/version.json b/carml/1.0.1/Microsoft.Management/managementGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Management/managementGroups/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/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..0f4c5f008 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(netAppAccount.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: netAppAccount +}] diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..029d5ebc0 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-anf-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/nfs3.parameters.json b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/nfs3.parameters.json new file mode 100644 index 000000000..1e5a91b39 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/nfs3.parameters.json @@ -0,0 +1,96 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-anf-nfs3-001" + }, + "capacityPools": { + "value": [ + { + "name": "<>-az-anfcp-x-001", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "name": "anf3-vol01-nfsv3", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv3" + ], + "exportPolicyRules": [ + { + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true, + "nfsv3": true, + "nfsv41": false, + "allowedClients": "0.0.0.0/0" + } + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "anf3-vol02-nfsv3", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv3" + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004" + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-anfcp-x-002", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + } + } +} diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/nfs41.parameters.json b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/nfs41.parameters.json new file mode 100644 index 000000000..2f961c144 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/.parameters/nfs41.parameters.json @@ -0,0 +1,106 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-anf-nfs41-001" + }, + "capacityPools": { + "value": [ + { + "name": "<>-az-anfcp-x-001", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "name": "anf4-vol01-nfsv41", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv4.1" + ], + "exportPolicyRules": [ + { + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true, + "nfsv3": false, + "nfsv41": true, + "allowedClients": "0.0.0.0/0" + } + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "anf4-vol02-nfsv41", + "usageThreshold": 107374182400, + "protocolTypes": [ + "NFSv4.1" + ], + "exportPolicyRules": [ + { + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true, + "nfsv3": false, + "nfsv41": true, + "allowedClients": "0.0.0.0/0" + } + ], + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-004" + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-anfcp-x-002", + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + } + } +} diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b18d132ed --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource capacityPool 'Microsoft.NetApp/netAppAccounts/capacityPools@2021-04-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(capacityPool.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: capacityPool +}] diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/deploy.bicep b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/deploy.bicep new file mode 100644 index 000000000..2e0364a82 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/deploy.bicep @@ -0,0 +1,109 @@ +@description('Required. The name of the NetApp account.') +param netAppAccountName string + +@description('Required. The name of the capacity pool.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. The pool service level.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104).') +param size int + +@description('Optional. The qos type of the pool.') +@allowed([ + 'Auto' + 'Manual' +]) +param qosType string = 'Auto' + +@description('Optional. List of volumnes to create in the capacity pool.') +param volumes array = [] + +@description('Optional. If enabled (true) the pool can contain cool Access enabled volumes.') +param coolAccess bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' existing = { + name: netAppAccountName +} + +resource capacityPool 'Microsoft.NetApp/netAppAccounts/capacityPools@2021-06-01' = { + name: name + parent: netAppAccount + location: location + tags: tags + properties: { + serviceLevel: serviceLevel + size: size + qosType: qosType + coolAccess: coolAccess + } +} + +@batchSize(1) +module capacityPool_volumes 'volumes/deploy.bicep' = [for (volume, index) in volumes: { + name: '${deployment().name}-Vol-${index}' + params: { + netAppAccountName: netAppAccount.name + capacityPoolName: capacityPool.name + name: volume.name + location: location + serviceLevel: serviceLevel + creationToken: contains(volume, 'creationToken') ? volume.creationToken : volume.name + usageThreshold: volume.usageThreshold + protocolTypes: contains(volume, 'protocolTypes') ? volume.protocolTypes : [] + subnetResourceId: volume.subnetResourceId + exportPolicyRules: contains(volume, 'exportPolicyRules') ? volume.exportPolicyRules : [] + roleAssignments: contains(volume, 'roleAssignments') ? volume.roleAssignments : [] + } +}] + +module capacityPool_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: capacityPool.id + } +}] + +@description('The name of the Capacity Pool.') +output name string = capacityPool.name + +@description('The resource ID of the Capacity Pool.') +output resourceId string = capacityPool.id + +@description('The name of the Resource Group the Capacity Pool was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/readme.md b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/readme.md new file mode 100644 index 000000000..b33362b9b --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/readme.md @@ -0,0 +1,97 @@ +# Azure NetApp Files Capacity Pools `[Microsoft.NetApp/netAppAccounts/capacityPools]` + +This template deploys capacity pools in an Azure NetApp Files. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | 2021-06-01 | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the capacity pool. | +| `netAppAccountName` | string | The name of the NetApp account. | +| `size` | int | Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `coolAccess` | bool | `False` | | If enabled (true) the pool can contain cool Access enabled volumes. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location of the pool volume. | +| `qosType` | string | `'Auto'` | `[Auto, Manual]` | The qos type of the pool. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serviceLevel` | string | `'Standard'` | `[Premium, Standard, StandardZRS, Ultra]` | The pool service level. | +| `tags` | object | `{object}` | | Tags for all resources. | +| `volumes` | _[volumes](volumes/readme.md)_ array | `[]` | | List of volumnes to create in the capacity pool. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Capacity Pool. | +| `resourceGroupName` | string | The name of the Resource Group the Capacity Pool was created in. | +| `resourceId` | string | The resource ID of the Capacity Pool. | + +## Template references + +- [Netappaccounts/Capacitypools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools) +- [Netappaccounts/Capacitypools/Volumes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools/volumes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/version.json b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/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/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..a58abbd99 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2021-04-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(volume.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: volume +}] diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/deploy.bicep b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/deploy.bicep new file mode 100644 index 000000000..46e957e1d --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/deploy.bicep @@ -0,0 +1,97 @@ +@description('Required. The name of the NetApp account.') +param netAppAccountName string + +@description('Required. The name of the capacity pool.') +param capacityPoolName string + +@description('Required. The name of the pool volume.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. The pool service level. Must match the one of the parent capacity pool.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription.') +param creationToken string = name + +@description('Required. Maximum storage quota allowed for a file system in bytes.') +param usageThreshold int + +@description('Optional. Set of protocol types.') +param protocolTypes array = [] + +@description('Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes.') +param subnetResourceId string + +@description('Optional. Export policy rules.') +param exportPolicyRules array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' existing = { + name: netAppAccountName + + resource capacityPool 'capacityPools@2021-06-01' existing = { + name: capacityPoolName + } +} + +resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2021-06-01' = { + name: name + parent: netAppAccount::capacityPool + location: location + properties: { + serviceLevel: serviceLevel + creationToken: creationToken + usageThreshold: usageThreshold + protocolTypes: protocolTypes + subnetId: subnetResourceId + exportPolicy: !empty(exportPolicyRules) ? { + rules: exportPolicyRules + } : null + } +} + +module volume_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: volume.id + } +}] + +@description('The name of the Volume.') +output name string = volume.name + +@description('The Resource ID of the Volume.') +output resourceId string = volume.id + +@description('The name of the Resource Group the Volume was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/readme.md b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/readme.md new file mode 100644 index 000000000..f85c270d7 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/readme.md @@ -0,0 +1,79 @@ +# Azure NetApp Files Capacity Pool Volumes `[Microsoft.NetApp/netAppAccounts/capacityPools/volumes]` + +This template deploys volumes in a capacity pool of an Azure NetApp files. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `capacityPoolName` | string | The name of the capacity pool. | +| `name` | string | The name of the pool volume. | +| `netAppAccountName` | string | The name of the NetApp account. | +| `subnetResourceId` | string | The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. | +| `usageThreshold` | int | Maximum storage quota allowed for a file system in bytes. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `creationToken` | string | `[parameters('name')]` | | A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exportPolicyRules` | array | `[]` | | Export policy rules. | +| `location` | string | `[resourceGroup().location]` | | Location of the pool volume. | +| `protocolTypes` | array | `[]` | | Set of protocol types. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serviceLevel` | string | `'Standard'` | `[Premium, Standard, StandardZRS, Ultra]` | The pool service level. Must match the one of the parent capacity pool. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Volume. | +| `resourceGroupName` | string | The name of the Resource Group the Volume was created in. | +| `resourceId` | string | The Resource ID of the Volume. | + +## Template references + +- [Netappaccounts/Capacitypools/Volumes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools/volumes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/version.json b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/capacityPools/volumes/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/carml/1.0.1/Microsoft.NetApp/netAppAccounts/deploy.bicep b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/deploy.bicep new file mode 100644 index 000000000..b386975de --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/deploy.bicep @@ -0,0 +1,120 @@ +@description('Required. The name of the NetApp account.') +param name string + +@description('Optional. Fully Qualified Active Directory DNS Domain Name (e.g. \'contoso.com\')') +param domainName string = '' + +@description('Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain.') +param domainJoinUser string = '' + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param domainJoinPassword string = '' + +@description('Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. \'OU=SecondLevel,OU=FirstLevel\').') +param domainJoinOU string = '' + +@description('Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed.') +param dnsServers string = '' + +@description('Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes') +param smbServerNamePrefix string = '' + +@description('Optional. Capacity pools to create.') +param capacityPools array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var activeDirectoryConnectionProperties = [ + { + username: !empty(domainName) ? domainJoinUser : null + password: !empty(domainName) ? domainJoinPassword : null + domain: !empty(domainName) ? domainName : null + dns: !empty(domainName) ? dnsServers : null + smbServerName: !empty(domainName) ? smbServerNamePrefix : null + organizationalUnit: !empty(domainJoinOU) ? domainJoinOU : null + } +] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2021-04-01' = { + name: name + tags: tags + location: location + properties: { + activeDirectories: !empty(domainName) ? activeDirectoryConnectionProperties : null + } +} + +resource netAppAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${netAppAccount.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: netAppAccount +} + +module netAppAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ANFAccount-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: netAppAccount.id + } +}] + +module netAppAccount_capacityPools 'capacityPools/deploy.bicep' = [for (capacityPool, index) in capacityPools: { + name: '${uniqueString(deployment().name, location)}-ANFAccount-CapPool-${index}' + params: { + netAppAccountName: netAppAccount.name + name: capacityPool.name + location: location + size: capacityPool.size + serviceLevel: contains(capacityPool, 'serviceLevel') ? capacityPool.serviceLevel : 'Standard' + qosType: contains(capacityPool, 'qosType') ? capacityPool.qosType : 'Auto' + volumes: contains(capacityPool, 'volumes') ? capacityPool.volumes : [] + coolAccess: contains(capacityPool, 'coolAccess') ? capacityPool.coolAccess : false + roleAssignments: contains(capacityPool, 'roleAssignments') ? capacityPool.roleAssignments : [] + } +}] + +@description('The name of the NetApp account.') +output name string = netAppAccount.name + +@description('The Resource ID of the NetApp account.') +output resourceId string = netAppAccount.id + +@description('The name of the Resource Group the NetApp account was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/readme.md b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/readme.md new file mode 100644 index 000000000..ad373a39a --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/readme.md @@ -0,0 +1,103 @@ +# Azure NetApp Files `[Microsoft.NetApp/netAppAccounts]` + +This template deploys Azure NetApp Files. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.NetApp/netAppAccounts` | 2021-04-01 | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | 2021-06-01 | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NetApp account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `capacityPools` | _[capacityPools](capacityPools/readme.md)_ array | `[]` | | Capacity pools to create. | +| `dnsServers` | string | `''` | | Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed. | +| `domainJoinOU` | string | `''` | | Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel'). | +| `domainJoinPassword` | secureString | `''` | | Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `domainJoinUser` | string | `''` | | Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. | +| `domainName` | string | `''` | | Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com') | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `smbServerNamePrefix` | string | `''` | | Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes | +| `tags` | object | `{object}` | | Tags for all resources. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NetApp account. | +| `resourceGroupName` | string | The name of the Resource Group the NetApp account was created in. | +| `resourceId` | string | The Resource ID of the NetApp account. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Netappaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-04-01/netAppAccounts) +- [Netappaccounts/Capacitypools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools) +- [Netappaccounts/Capacitypools/Volumes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.NetApp/2021-06-01/netAppAccounts/capacityPools/volumes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.NetApp/netAppAccounts/version.json b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.NetApp/netAppAccounts/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/carml/1.0.1/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..a7bda4c41 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource applicationGateway 'Microsoft.Network/applicationGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(applicationGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: applicationGateway +}] diff --git a/carml/1.0.1/Microsoft.Network/applicationGateways/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/applicationGateways/.parameters/parameters.json new file mode 100644 index 000000000..e0a8603a8 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationGateways/.parameters/parameters.json @@ -0,0 +1,364 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apgw-x-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "webApplicationFirewallConfiguration": { + "value": { + "enabled": true, + "firewallMode": "Detection", + "ruleSetType": "OWASP", + "ruleSetVersion": "3.0", + "disabledRuleGroups": [], + "requestBodyCheck": true, + "maxRequestBodySizeInKb": 128, + "fileUploadLimitInMb": 100 + } + }, + "enableHttp2": { + "value": true + }, + "backendAddressPools": { + "value": [ + { + "name": "appServiceBackendPool", + "properties": { + "backendAddresses": [ + { + "fqdn": "aghapp.azurewebsites.net" + } + ] + } + }, + { + "name": "privateVmBackendPool", + "properties": { + "backendAddresses": [ + { + "ipAddress": "10.0.0.4" + } + ] + } + } + ] + }, + "backendHttpSettingsCollection": { + "value": [ + { + "name": "appServiceBackendHttpsSetting", + "properties": { + "port": 443, + "protocol": "Https", + "cookieBasedAffinity": "Disabled", + "pickHostNameFromBackendAddress": true, + "requestTimeout": 30 + } + }, + { + "name": "privateVmHttpSetting", + "properties": { + "port": 80, + "protocol": "Http", + "cookieBasedAffinity": "Disabled", + "pickHostNameFromBackendAddress": false, + "requestTimeout": 30, + "probe": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/probes/privateVmHttpSettingProbe" + } + } + } + ] + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "private", + "properties": { + "privateIPAddress": "10.0.8.6", + "privateIPAllocationMethod": "Static", + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-007" + } + } + }, + { + "name": "public", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-apgw" + } + } + } + ] + }, + "frontendPorts": { + "value": [ + { + "name": "port443", + "properties": { + "port": 443 + } + }, + { + "name": "port4433", + "properties": { + "port": 4433 + } + }, + { + "name": "port80", + "properties": { + "port": 80 + } + }, + { + "name": "port8080", + "properties": { + "port": 8080 + } + } + ] + }, + "httpListeners": { + "value": [ + { + "name": "public443", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/public" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port443" + }, + "sslCertificate": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/sslCertificates/<>-az-apgw-x-001-ssl-certificate" + }, + "protocol": "https", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "private4433", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/private" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port4433" + }, + "sslCertificate": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/sslCertificates/<>-az-apgw-x-001-ssl-certificate" + }, + "protocol": "https", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "httpRedirect80", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/public" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port80" + }, + "protocol": "Http", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "httpRedirect8080", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/private" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port8080" + }, + "protocol": "Http", + "hostNames": [], + "requireServerNameIndication": false + } + } + ] + }, + "gatewayIPConfigurations": { + "value": [ + { + "name": "apw-ip-configuration", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-007" + } + } + } + ] + }, + "probes": { + "value": [ + { + "name": "privateVmHttpSettingProbe", + "properties": { + "protocol": "Http", + "host": "10.0.0.4", + "path": "/", + "interval": 60, + "timeout": 15, + "unhealthyThreshold": 5, + "pickHostNameFromBackendHttpSettings": false, + "minServers": 3, + "match": { + "statusCodes": [ + "200", + "401" + ] + } + } + } + ] + }, + "redirectConfigurations": { + "value": [ + { + "name": "httpRedirect80", + "properties": { + "redirectType": "Permanent", + "targetListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/public443" + }, + "includePath": true, + "includeQueryString": true, + "requestRoutingRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/requestRoutingRules/httpRedirect80-public443" + } + ] + } + }, + { + "name": "httpRedirect8080", + "properties": { + "redirectType": "Permanent", + "targetListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/private4433" + }, + "includePath": true, + "includeQueryString": true, + "requestRoutingRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/requestRoutingRules/httpRedirect8080-private4433" + } + ] + } + } + ] + }, + "requestRoutingRules": { + "value": [ + { + "name": "public443-appServiceBackendHttpsSetting-appServiceBackendHttpsSetting", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/public443" + }, + "backendAddressPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendAddressPools/appServiceBackendPool" + }, + "backendHttpSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendHttpSettingsCollection/appServiceBackendHttpsSetting" + } + } + }, + { + "name": "private4433-privateVmHttpSetting-privateVmHttpSetting", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/private4433" + }, + "backendAddressPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendAddressPools/privateVmBackendPool" + }, + "backendHttpSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendHttpSettingsCollection/privateVmHttpSetting" + } + } + }, + { + "name": "httpRedirect80-public443", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/httpRedirect80" + }, + "redirectConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/redirectConfigurations/httpRedirect80" + } + } + }, + { + "name": "httpRedirect8080-private4433", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/httpRedirect8080" + }, + "redirectConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/redirectConfigurations/httpRedirect8080" + } + } + } + ] + }, + "sku": { + "value": "WAF_v2" + }, + "sslCertificates": { + "value": [ + { + "name": "<>-az-apgw-x-001-ssl-certificate", + "properties": { + "keyVaultSecretId": "https://adp-<>-az-kv-x-001.vault.azure.net/secrets/applicationGatewaySslCertificate02/40b9b1a7a69e48cfa1e36f24b97b8799" + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/applicationGateways/deploy.bicep b/carml/1.0.1/Microsoft.Network/applicationGateways/deploy.bicep new file mode 100644 index 000000000..c94b24d39 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationGateways/deploy.bicep @@ -0,0 +1,363 @@ +@description('Required. Name of the Application Gateway.') +@maxLength(24) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Authentication certificates of the application gateway resource.') +param authenticationCertificates array = [] + +@description('Optional. Upper bound on number of Application Gateway capacity.') +param autoscaleMaxCapacity int = -1 + +@description('Optional. Lower bound on number of Application Gateway capacity.') +param autoscaleMinCapacity int = -1 + +@description('Optional. Backend address pool of the application gateway resource.') +param backendAddressPools array = [] + +@description('Optional. Backend http settings of the application gateway resource.') +param backendHttpSettingsCollection array = [] + +@description('Optional. Custom error configurations of the application gateway resource.') +param customErrorConfigurations array = [] + +@description('Optional. Whether FIPS is enabled on the application gateway resource.') +param enableFips bool = false + +@description('Optional. Whether HTTP2 is enabled on the application gateway resource.') +param enableHttp2 bool = false + +@description('Optional. The resource ID of an associated firewall policy.') +param firewallPolicyId string = '' + +@description('Optional. Frontend IP addresses of the application gateway resource.') +param frontendIPConfigurations array = [] + +@description('Optional. Frontend ports of the application gateway resource.') +param frontendPorts array = [] + +@description('Optional. Subnets of the application gateway resource.') +param gatewayIPConfigurations array = [] + +@description('Optional. Enable request buffering.') +param enableRequestBuffering bool = false + +@description('Optional. Enable response buffering.') +param enableResponseBuffering bool = false + +@description('Optional. Http listeners of the application gateway resource.') +param httpListeners array = [] + +@description('Optional. Load distribution policies of the application gateway resource.') +param loadDistributionPolicies array = [] + +@description('Optional. PrivateLink configurations on application gateway.') +param privateLinkConfigurations array = [] + +@description('Optional. Probes of the application gateway resource.') +param probes array = [] + +@description('Optional. Redirect configurations of the application gateway resource.') +param redirectConfigurations array = [] + +@description('Optional. Request routing rules of the application gateway resource.') +param requestRoutingRules array = [] + +@description('Optional. Rewrite rules for the application gateway resource. ') +param rewriteRuleSets array = [] + +@description('Optional. The name of the SKU for the Application Gateway.') +@allowed([ + 'Standard_Small' + 'Standard_Medium' + 'Standard_Large' + 'WAF_Medium' + 'WAF_Large' + 'Standard_v2' + 'WAF_v2' +]) +param sku string = 'WAF_Medium' + +@description('Optional. The number of Application instances to be configured.') +@minValue(1) +@maxValue(10) +param capacity int = 2 + +@description('Optional. SSL certificates of the application gateway resource.') +param sslCertificates array = [] + +@description('Optional. Ssl cipher suites to be enabled in the specified order to application gateway.') +@allowed([ + 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256' + 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256' + 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA' + 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA' + 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA' + 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256' + 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256' + 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA' + 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384' + 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA' + 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256' + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA' + 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_RSA_WITH_3DES_EDE_CBC_SHA' + 'TLS_RSA_WITH_AES_128_CBC_SHA' + 'TLS_RSA_WITH_AES_128_CBC_SHA256' + 'TLS_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_RSA_WITH_AES_256_CBC_SHA' + 'TLS_RSA_WITH_AES_256_CBC_SHA256' + 'TLS_RSA_WITH_AES_256_GCM_SHA384' +]) +param sslPolicyCipherSuites array = [ + 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' +] + +@description('Optional. Ssl protocol enums.') +@allowed([ + 'TLSv1_0' + 'TLSv1_1' + 'TLSv1_2' +]) +param sslPolicyMinProtocolVersion string = 'TLSv1_2' + +@description('Optional. Ssl predefined policy name enums.') +@allowed([ + 'AppGwSslPolicy20150501' + 'AppGwSslPolicy20170401' + 'AppGwSslPolicy20170401S' + '' +]) +param sslPolicyName string = '' + +@description('Optional. Type of Ssl Policy.') +@allowed([ + 'Custom' + 'Predefined' +]) +param sslPolicyType string = 'Custom' + +@description('Optional. SSL profiles of the application gateway resource.') +param sslProfiles array = [] + +@description('Optional. Trusted client certificates of the application gateway resource.') +param trustedClientCertificates array = [] + +@description('Optional. Trusted Root certificates of the application gateway resource.') +param trustedRootCertificates array = [] + +@description('Optional. URL path map of the application gateway resource.') +param urlPathMaps array = [] + +@description('Optional. Application gateway web application firewall configuration.') +param webApplicationFirewallConfiguration object = {} + +@description('Optional. A list of availability zones denoting where the resource needs to come from.') +param zones array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ApplicationGatewayAccessLog' + 'ApplicationGatewayPerformanceLog' + 'ApplicationGatewayFirewallLog' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ApplicationGatewayAccessLog' + 'ApplicationGatewayPerformanceLog' + 'ApplicationGatewayFirewallLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource applicationGateway 'Microsoft.Network/applicationGateways@2021-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: union({ + authenticationCertificates: authenticationCertificates + autoscaleConfiguration: autoscaleMaxCapacity > 0 && autoscaleMinCapacity > 0 ? { + maxCapacity: autoscaleMaxCapacity + minCapacity: autoscaleMinCapacity + } : null + backendAddressPools: backendAddressPools + backendHttpSettingsCollection: backendHttpSettingsCollection + customErrorConfigurations: customErrorConfigurations + enableHttp2: enableHttp2 + firewallPolicy: !empty(firewallPolicyId) ? { + id: firewallPolicyId + } : null + forceFirewallPolicyAssociation: !empty(firewallPolicyId) + frontendIPConfigurations: frontendIPConfigurations + frontendPorts: frontendPorts + gatewayIPConfigurations: gatewayIPConfigurations + globalConfiguration: { + enableRequestBuffering: enableRequestBuffering + enableResponseBuffering: enableResponseBuffering + } + httpListeners: httpListeners + loadDistributionPolicies: loadDistributionPolicies + privateLinkConfigurations: privateLinkConfigurations + probes: probes + redirectConfigurations: redirectConfigurations + requestRoutingRules: requestRoutingRules + rewriteRuleSets: rewriteRuleSets + sku: { + name: sku + tier: endsWith(sku, 'v2') ? sku : substring(sku, 0, indexOf(sku, '_')) + capacity: autoscaleMaxCapacity > 0 && autoscaleMinCapacity > 0 ? null : capacity + } + sslCertificates: sslCertificates + sslPolicy: { + cipherSuites: sslPolicyCipherSuites + minProtocolVersion: sslPolicyMinProtocolVersion + policyName: empty(sslPolicyName) ? null : sslPolicyName + policyType: sslPolicyType + } + sslProfiles: sslProfiles + trustedClientCertificates: trustedClientCertificates + trustedRootCertificates: trustedRootCertificates + urlPathMaps: urlPathMaps + webApplicationFirewallConfiguration: webApplicationFirewallConfiguration + }, (enableFips ? { + enableFips: enableFips + } : {}), {}) + zones: zones +} + +resource applicationGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${applicationGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: applicationGateway +} + +resource applicationGateway_diagnosticSettingName 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId + workspaceId: empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId + eventHubAuthorizationRuleId: empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId + eventHubName: empty(diagnosticEventHubName) ? null : diagnosticEventHubName + metrics: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsMetrics + logs: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsLogs + } + scope: applicationGateway +} + +module applicationGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: applicationGateway.id + } +}] + +@description('The name of the application gateway') +output name string = applicationGateway.name + +@description('The resource ID of the application gateway') +output resourceId string = applicationGateway.id + +@description('The resource group the application gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/applicationGateways/readme.md b/carml/1.0.1/Microsoft.Network/applicationGateways/readme.md new file mode 100644 index 000000000..cf11dd4a7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationGateways/readme.md @@ -0,0 +1,687 @@ +# Network Application Gateways `[Microsoft.Network/applicationGateways]` + +This module deploys Network ApplicationGateways. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/applicationGateways` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Application Gateway. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authenticationCertificates` | array | `[]` | | Authentication certificates of the application gateway resource. | +| `autoscaleMaxCapacity` | int | `-1` | | Upper bound on number of Application Gateway capacity. | +| `autoscaleMinCapacity` | int | `-1` | | Lower bound on number of Application Gateway capacity. | +| `backendAddressPools` | array | `[]` | | Backend address pool of the application gateway resource. | +| `backendHttpSettingsCollection` | array | `[]` | | Backend http settings of the application gateway resource. | +| `capacity` | int | `2` | | The number of Application instances to be configured. | +| `customErrorConfigurations` | array | `[]` | | Custom error configurations of the application gateway resource. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogCategoriesToEnable` | array | `[ApplicationGatewayAccessLog, ApplicationGatewayPerformanceLog, ApplicationGatewayFirewallLog]` | `[ApplicationGatewayAccessLog, ApplicationGatewayPerformanceLog, ApplicationGatewayFirewallLog]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableFips` | bool | `False` | | Whether FIPS is enabled on the application gateway resource. | +| `enableHttp2` | bool | `False` | | Whether HTTP2 is enabled on the application gateway resource. | +| `enableRequestBuffering` | bool | `False` | | Enable request buffering. | +| `enableResponseBuffering` | bool | `False` | | Enable response buffering. | +| `firewallPolicyId` | string | `''` | | The resource ID of an associated firewall policy. | +| `frontendIPConfigurations` | array | `[]` | | Frontend IP addresses of the application gateway resource. | +| `frontendPorts` | array | `[]` | | Frontend ports of the application gateway resource. | +| `gatewayIPConfigurations` | array | `[]` | | Subnets of the application gateway resource. | +| `httpListeners` | array | `[]` | | Http listeners of the application gateway resource. | +| `loadDistributionPolicies` | array | `[]` | | Load distribution policies of the application gateway resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateLinkConfigurations` | array | `[]` | | PrivateLink configurations on application gateway. | +| `probes` | array | `[]` | | Probes of the application gateway resource. | +| `redirectConfigurations` | array | `[]` | | Redirect configurations of the application gateway resource. | +| `requestRoutingRules` | array | `[]` | | Request routing rules of the application gateway resource. | +| `rewriteRuleSets` | array | `[]` | | Rewrite rules for the application gateway resource. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'WAF_Medium'` | `[Standard_Small, Standard_Medium, Standard_Large, WAF_Medium, WAF_Large, Standard_v2, WAF_v2]` | The name of the SKU for the Application Gateway. | +| `sslCertificates` | array | `[]` | | SSL certificates of the application gateway resource. | +| `sslPolicyCipherSuites` | array | `[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]` | `[TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384]` | Ssl cipher suites to be enabled in the specified order to application gateway. | +| `sslPolicyMinProtocolVersion` | string | `'TLSv1_2'` | `[TLSv1_0, TLSv1_1, TLSv1_2]` | Ssl protocol enums. | +| `sslPolicyName` | string | `''` | `[AppGwSslPolicy20150501, AppGwSslPolicy20170401, AppGwSslPolicy20170401S, ]` | Ssl predefined policy name enums. | +| `sslPolicyType` | string | `'Custom'` | `[Custom, Predefined]` | Type of Ssl Policy. | +| `sslProfiles` | array | `[]` | | SSL profiles of the application gateway resource. | +| `tags` | object | `{object}` | | Resource tags. | +| `trustedClientCertificates` | array | `[]` | | Trusted client certificates of the application gateway resource. | +| `trustedRootCertificates` | array | `[]` | | Trusted Root certificates of the application gateway resource. | +| `urlPathMaps` | array | `[]` | | URL path map of the application gateway resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `webApplicationFirewallConfiguration` | object | `{object}` | | Application gateway web application firewall configuration. | +| `zones` | array | `[]` | | A list of availability zones denoting where the resource needs to come from. | + + +### Parameter Usage: `authenticationCertificates` + +```json +"authenticationCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string" + } + } + ] +} +``` + +### Parameter Usage: `backendAddressPools` + +```json +"backendAddressPools": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddresses": [ + { + "fqdn": "string", + "ipAddress": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `backendHttpSettingsCollection` + +```json +"backendHttpSettingsCollection": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "affinityCookieName": "string", + "authenticationCertificates": [ + { + "id": "string" + } + ], + "connectionDraining": { + "drainTimeoutInSec": "int", + "enabled": "bool" + }, + "cookieBasedAffinity": "string", + "hostName": "string", + "path": "string", + "pickHostNameFromBackendAddress": "bool", + "port": "int", + "probe": { + "id": "string" + }, + "probeEnabled": "bool", + "protocol": "string", + "requestTimeout": "int", + "trustedRootCertificates": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `customErrorConfigurations` + +```json +"customErrorConfigurations": { + "value": [ + { + "customErrorPageUrl": "string", + "statusCode": "string" + } + ] +} +``` + +### Parameter Usage: `frontendIPConfigurations` + +```json +"frontendIPConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "privateIPAddress": "string", + "privateIPAllocationMethod": "string", + "privateLinkConfiguration": { + "id": "string" + }, + "publicIPAddress": { + "id": "string" + }, + "subnet": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `frontendPorts` + +```json +"frontendPorts": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "port": "int" + } + } + ] +} +``` + +### Parameter Usage: `gatewayIPConfigurations` + +```json +"gatewayIPConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "subnet": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `httpListeners` + +```json +"httpListeners": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "customErrorConfigurations": [ + { + "customErrorPageUrl": "string", + "statusCode": "string" + } + ], + "firewallPolicy": { + "id": "string" + }, + "frontendIPConfiguration": { + "id": "string" + }, + "frontendPort": { + "id": "string" + }, + "hostName": "string", + "hostNames": [ "string" ], + "protocol": "string", + "requireServerNameIndication": "bool", + "sslCertificate": { + "id": "string" + }, + "sslProfile": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `loadDistributionPolicies` + +```json +"loadDistributionPolicies": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "loadDistributionAlgorithm": "string", + "loadDistributionTargets": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "weightPerServer": "int" + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `privateLinkConfigurations` + +```json +"privateLinkConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "ipConfigurations": [ + { + "id": "string", + "name": "string", + "properties": { + "primary": "bool", + "privateIPAddress": "string", + "privateIPAllocationMethod": "string", + "subnet": { + "id": "string" + } + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `probes` + +```json +"probes": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "host": "string", + "interval": "int", + "match": { + "body": "string", + "statusCodes": [ "string" ] + }, + "minServers": "int", + "path": "string", + "pickHostNameFromBackendHttpSettings": "bool", + "port": "int", + "protocol": "string", + "timeout": "int", + "unhealthyThreshold": "int" + } + } + ] +} +``` + +### Parameter Usage: `redirectConfigurations` + +```json +"redirectConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "includePath": "bool", + "includeQueryString": "bool", + "pathRules": [ + { + "id": "string" + } + ], + "redirectType": "string", + "requestRoutingRules": [ + { + "id": "string" + } + ], + "targetListener": { + "id": "string" + }, + "targetUrl": "string", + "urlPathMaps": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `requestRoutingRules` + +```json +"requestRoutingRules": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "backendHttpSettings": { + "id": "string" + }, + "httpListener": { + "id": "string" + }, + "loadDistributionPolicy": { + "id": "string" + }, + "priority": "int", + "redirectConfiguration": { + "id": "string" + }, + "rewriteRuleSet": { + "id": "string" + }, + "ruleType": "string", + "urlPathMap": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `rewriteRuleSets` + +```json +"rewriteRuleSets": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "rewriteRules": [ + { + "actionSet": { + "requestHeaderConfigurations": [ + { + "headerName": "string", + "headerValue": "string" + } + ], + "responseHeaderConfigurations": [ + { + "headerName": "string", + "headerValue": "string" + } + ], + "urlConfiguration": { + "modifiedPath": "string", + "modifiedQueryString": "string", + "reroute": "bool" + } + }, + "conditions": [ + { + "ignoreCase": "bool", + "negate": "bool", + "pattern": "string", + "variable": "string" + } + ], + "name": "string", + "ruleSequence": "int" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `sslCertificates` + +```json +"sslCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string", + "keyVaultSecretId": "string", + "password": "string" + } + } + ] +} +``` + +### Parameter Usage: `sslProfiles` + +```json +"sslProfiles": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "clientAuthConfiguration": { + "verifyClientCertIssuerDN": "bool" + }, + "sslPolicy": { + "cipherSuites": [ "string" ], + "disabledSslProtocols": [ "string" ], + "minProtocolVersion": "string", + "policyName": "string", + "policyType": "string" + }, + "trustedClientCertificates": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `trustedClientCertificates` + +```json +"trustedClientCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string" + } + } + ] +} +``` + +### Parameter Usage: `trustedRootCertificates` + +```json +"trustedRootCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string", + "keyVaultSecretId": "string" + } + } + ] +} +``` + +### Parameter Usage: `urlPathMaps` + +```json +"urlPathMaps": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "defaultBackendAddressPool": { + "id": "string" + }, + "defaultBackendHttpSettings": { + "id": "string" + }, + "defaultLoadDistributionPolicy": { + "id": "string" + }, + "defaultRedirectConfiguration": { + "id": "string" + }, + "defaultRewriteRuleSet": { + "id": "string" + }, + "pathRules": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "backendHttpSettings": { + "id": "string" + }, + "firewallPolicy": { + "id": "string" + }, + "loadDistributionPolicy": { + "id": "string" + }, + "paths": [ "string" ], + "redirectConfiguration": { + "id": "string" + }, + "rewriteRuleSet": { + "id": "string" + } + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application gateway | +| `resourceGroupName` | string | The resource group the application gateway was deployed into | +| `resourceId` | string | The resource ID of the application gateway | + +## Template references + +- [Applicationgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/applicationGateways) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/applicationGateways/version.json b/carml/1.0.1/Microsoft.Network/applicationGateways/version.json new file mode 100644 index 000000000..badc0a228 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationGateways/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.5" +} diff --git a/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..322247562 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(applicationSecurityGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: applicationSecurityGroup +}] diff --git a/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json new file mode 100644 index 000000000..f740e20b4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-asg-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/deploy.bicep b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/deploy.bicep new file mode 100644 index 000000000..924f02eb5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. Name of the Application Security Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource applicationSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${applicationSecurityGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: applicationSecurityGroup +} + +module applicationSecurityGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppSecurityGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: applicationSecurityGroup.id + } +}] + +@description('The resource group the application security group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the application security group') +output resourceId string = applicationSecurityGroup.id + +@description('The name of the application security group') +output name string = applicationSecurityGroup.name diff --git a/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/readme.md b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/readme.md new file mode 100644 index 000000000..1f3d51fe7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/readme.md @@ -0,0 +1,92 @@ +# Application Security Groups `[Microsoft.Network/applicationSecurityGroups]` + +This module deploys an application security group. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/applicationSecurityGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Application Security Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application security group | +| `resourceGroupName` | string | The resource group the application security group was deployed into | +| `resourceId` | string | The resource ID of the application security group | + +## Template references + +- [Applicationsecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/applicationSecurityGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/version.json b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/applicationSecurityGroups/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/carml/1.0.1/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c2ca9c2a9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(azureFirewall.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: azureFirewall +}] diff --git a/carml/1.0.1/Microsoft.Network/azureFirewalls/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/azureFirewalls/.parameters/parameters.json new file mode 100644 index 000000000..864f62df5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/azureFirewalls/.parameters/parameters.json @@ -0,0 +1,135 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-azfw-x-001" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + }, + "ipConfigurations": { + "value": [ + { + "name": "ipConfig01", + "publicIPAddressResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-fw", + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-azfw/subnets/AzureFirewallSubnet" + } + ] + }, + "applicationRuleCollections": { + "value": [ + { + "name": "allow-app-rules", + "properties": { + "priority": 100, + "action": { + "type": "allow" + }, + "rules": [ + { + "name": "allow-ase-tags", + "sourceAddresses": [ + "*" + ], + "protocols": [ + { + "protocolType": "HTTP", + "port": "80" + }, + { + "protocolType": "HTTPS", + "port": "443" + } + ], + "fqdnTags": [ + "AppServiceEnvironment", + "WindowsUpdate" + ] + }, + { + "name": "allow-ase-management", + "sourceAddresses": [ + "*" + ], + "protocols": [ + { + "protocolType": "HTTP", + "port": "80" + }, + { + "protocolType": "HTTPS", + "port": "443" + } + ], + "targetFqdns": [ + "management.azure.com" + ] + } + ] + } + } + ] + }, + "networkRuleCollections": { + "value": [ + { + "name": "allow-network-rules", + "properties": { + "priority": 100, + "action": { + "type": "allow" + }, + "rules": [ + { + "name": "allow-ntp", + "sourceAddresses": [ + "*" + ], + "destinationAddresses": [ + "*" + ], + "destinationPorts": [ + "123", + "12000" + ], + "protocols": [ + "Any" + ] + } + ] + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/azureFirewalls/deploy.bicep b/carml/1.0.1/Microsoft.Network/azureFirewalls/deploy.bicep new file mode 100644 index 000000000..b60a82504 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/azureFirewalls/deploy.bicep @@ -0,0 +1,224 @@ +@description('Required. Name of the Azure Firewall.') +param name string + +@description('Optional. Name of an Azure Firewall SKU.') +@allowed([ + 'AZFW_VNet' + 'AZFW_Hub' +]) +param azureSkuName string = 'AZFW_VNet' + +@description('Optional. Tier of an Azure Firewall.') +@allowed([ + 'Standard' + 'Premium' +]) +param azureSkuTier string = 'Standard' + +@description('Optional. Collection of application rule collections used by Azure Firewall.') +param applicationRuleCollections array = [] + +@description('Optional. Collection of network rule collections used by Azure Firewall.') +param networkRuleCollections array = [] + +@description('Optional. Collection of NAT rule collections used by Azure Firewall.') +param natRuleCollections array = [] + +@description('Required. List of IP Configurations.') +param ipConfigurations array + +@description('Optional. Resource ID of the Firewall Policy that should be attached.') +param firewallPolicyId string = '' + +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +@description('Optional. The operation mode for Threat Intel.') +param threatIntelMode string = 'Deny' + +@description('Optional. Zone numbers e.g. 1,2,3.') +param zones array = [ + '1' + '2' + '3' +] + +@description('Optional. Diagnostic Storage Account resource identifier') +param diagnosticStorageAccountId string = '' + +@description('Optional. Log Analytics workspace resource identifier') +param diagnosticWorkspaceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the Azure Firewall resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of firewall logs that will be streamed.') +@allowed([ + 'AzureFirewallApplicationRule' + 'AzureFirewallNetworkRule' + 'AzureFirewallDnsProxy' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AzureFirewallApplicationRule' + 'AzureFirewallNetworkRule' + 'AzureFirewallDnsProxy' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +var ipConfigurations_var = [for ipConfiguration in ipConfigurations: { + name: ipConfiguration.name + properties: { + publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? { + id: ipConfiguration.publicIPAddressResourceId + } : null + subnet: contains(ipConfiguration, 'subnetResourceId') ? { + id: ipConfiguration.subnetResourceId + } : null + } +}] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2021-05-01' = { + name: name + location: location + zones: length(zones) == 0 ? null : zones + tags: tags + properties: { + threatIntelMode: threatIntelMode + firewallPolicy: empty(firewallPolicyId) ? null : { + id: firewallPolicyId + } + ipConfigurations: ipConfigurations_var + sku: { + name: azureSkuName + tier: azureSkuTier + } + applicationRuleCollections: applicationRuleCollections + natRuleCollections: natRuleCollections + networkRuleCollections: networkRuleCollections + } +} + +resource azureFirewall_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureFirewall.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureFirewall +} + +resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: azureFirewall +} + +module azureFirewall_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AzFW-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureFirewall.id + } +}] + +@description('The resource ID of the Azure firewall') +output resourceId string = azureFirewall.id + +@description('The name of the Azure firewall') +output name string = azureFirewall.name + +@description('The resource group the Azure firewall was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The private IP of the Azure firewall') +output privateIp string = azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + +@description('List of Application Rule Collections') +output applicationRuleCollections array = applicationRuleCollections + +@description('List of Network Rule Collections') +output networkRuleCollections array = networkRuleCollections + +@description('Collection of NAT rule collections used by Azure Firewall') +output natRuleCollections array = natRuleCollections diff --git a/carml/1.0.1/Microsoft.Network/azureFirewalls/readme.md b/carml/1.0.1/Microsoft.Network/azureFirewalls/readme.md new file mode 100644 index 000000000..ab565b8cc --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/azureFirewalls/readme.md @@ -0,0 +1,121 @@ +# Azure Firewalls `[Microsoft.Network/azureFirewalls]` + +This module deploys a firewall. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/azureFirewalls` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `ipConfigurations` | array | List of IP Configurations. | +| `name` | string | Name of the Azure Firewall. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `applicationRuleCollections` | array | `[]` | | Collection of application rule collections used by Azure Firewall. | +| `azureSkuName` | string | `'AZFW_VNet'` | `[AZFW_VNet, AZFW_Hub]` | Name of an Azure Firewall SKU. | +| `azureSkuTier` | string | `'Standard'` | `[Standard, Premium]` | Tier of an Azure Firewall. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[AzureFirewallApplicationRule, AzureFirewallNetworkRule, AzureFirewallDnsProxy]` | `[AzureFirewallApplicationRule, AzureFirewallNetworkRule, AzureFirewallDnsProxy]` | The name of firewall logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Diagnostic Storage Account resource identifier | +| `diagnosticWorkspaceId` | string | `''` | | Log Analytics workspace resource identifier | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `firewallPolicyId` | string | `''` | | Resource ID of the Firewall Policy that should be attached. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `natRuleCollections` | array | `[]` | | Collection of NAT rule collections used by Azure Firewall. | +| `networkRuleCollections` | array | `[]` | | Collection of network rule collections used by Azure Firewall. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the Azure Firewall resource. | +| `threatIntelMode` | string | `'Deny'` | `[Alert, Deny, Off]` | The operation mode for Threat Intel. | +| `zones` | array | `[1, 2, 3]` | | Zone numbers e.g. 1,2,3. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationRuleCollections` | array | List of Application Rule Collections | +| `name` | string | The name of the Azure firewall | +| `natRuleCollections` | array | Collection of NAT rule collections used by Azure Firewall | +| `networkRuleCollections` | array | List of Network Rule Collections | +| `privateIp` | string | The private IP of the Azure firewall | +| `resourceGroupName` | string | The resource group the Azure firewall was deployed into | +| `resourceId` | string | The resource ID of the Azure firewall | + +## Considerations + +The `applicationRuleCollections` parameter accepts a JSON Array of AzureFirewallApplicationRule objects. +The `networkRuleCollections` parameter accepts a JSON Array of AzureFirewallNetworkRuleCollection objects. + +## Template references + +- [Azurefirewalls](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/azureFirewalls) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/azureFirewalls/version.json b/carml/1.0.1/Microsoft.Network/azureFirewalls/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/azureFirewalls/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/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep b/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep new file mode 100644 index 000000000..cc9a0eb90 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep @@ -0,0 +1,153 @@ +@description('Required. The name of the Public IP Address') +param name string + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. The public IP address allocation method. - Static or Dynamic.') +param publicIPAllocationMethod string = 'Dynamic' + +@description('Optional. Public IP Address sku Name') +param skuName string = 'Basic' + +@description('Optional. Public IP Address pricing tier') +param skuTier string = 'Regional' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource identifier of log analytics.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIPPrefix = { + id: publicIPPrefixResourceId +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + properties: { + publicIPAddressVersion: 'IPv4' + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + idleTimeoutInMinutes: 4 + ipTags: [] + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac 'nested_publicIPAddress_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The resource group the public IP address was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address') +output resourceId string = publicIpAddress.id diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep b/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep new file mode 100644 index 000000000..87e8e8d34 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpAddress +}] diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..08f2129f0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource azureBastion 'Microsoft.Network/bastionHosts@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(azureBastion.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: azureBastion +}] diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/bastionHosts/.parameters/min.parameters.json new file mode 100644 index 000000000..6ef38853f --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/.parameters/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": "<>-az-bas-min-001" + }, + "vNetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-002" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/bastionHosts/.parameters/parameters.json new file mode 100644 index 000000000..0b1cd0d25 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/.parameters/parameters.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-bas-x-001" + }, + "vNetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "publicIPAddressId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-bas" + }, + "skuType": { + "value": "Standard" + }, + "scaleUnits": { + "value": 4 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/deploy.bicep b/carml/1.0.1/Microsoft.Network/bastionHosts/deploy.bicep new file mode 100644 index 000000000..8a0d46168 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. Name of the Azure Bastion resource') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Shared services Virtual Network resource identifier') +param vNetId string + +@description('Optional. Specifies the resource ID of the existing public IP to be leveraged by Azure Bastion.') +param publicIPAddressId string = '' + +@description('Optional. Specifies the properties of the public IP to create and be used by Azure Bastion. If it\'s not provided and publicIPAddressId is empty, a \'-pip\' suffix will be appended to the Bastion\'s name.') +param publicIPAddressObject object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@allowed([ + 'Basic' + 'Standard' +]) +@description('Optional. The SKU of this Bastion Host.') +param skuType string = 'Basic' + +@description('Optional. The scale units for the Bastion Host resource.') +param scaleUnits int = 2 + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Optional. The name of bastion logs that will be streamed.') +@allowed([ + 'BastionAuditLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'BastionAuditLogs' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var scaleUnits_var = skuType == 'Basic' ? 2 : scaleUnits + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource publicIPAddressExisting 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = if (!empty(publicIPAddressId)) { + name: last(split(publicIPAddressId, '/')) + scope: resourceGroup(split(publicIPAddressId, '/')[2], split(publicIPAddressId, '/')[4]) +} + +module publicIPAddress '.bicep/nested_publicIPAddress.bicep' = if (empty(publicIPAddressId)) { + name: '${uniqueString(deployment().name, location)}-Bastion-PIP' + params: { + name: contains(publicIPAddressObject, 'name') ? (!(empty(publicIPAddressObject.name)) ? publicIPAddressObject.name : '${name}-pip') : '${name}-pip' + publicIPPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) ? publicIPAddressObject.publicIPPrefixResourceId : '') : '' + publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) ? publicIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' + skuName: contains(publicIPAddressObject, 'skuName') ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') : 'Standard' + skuTier: contains(publicIPAddressObject, 'skuTier') ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') : 'Regional' + roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) : [] + diagnosticMetricsToEnable: contains(publicIPAddressObject, 'diagnosticMetricsToEnable') ? (!(empty(publicIPAddressObject.diagnosticMetricsToEnable)) ? publicIPAddressObject.diagnosticMetricsToEnable : [ + 'AllMetrics' + ]) : [ + 'AllMetrics' + ] + diagnosticLogCategoriesToEnable: contains(publicIPAddressObject, 'diagnosticLogCategoriesToEnable') ? (!(empty(publicIPAddressObject.diagnosticLogCategoriesToEnable)) ? publicIPAddressObject.diagnosticLogCategoriesToEnable : [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' + ]) : [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' + ] + location: location + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + lock: lock + tags: tags + } +} + +resource azureBastion 'Microsoft.Network/bastionHosts@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuType + } + properties: { + scaleUnits: scaleUnits_var + ipConfigurations: [ + { + name: 'IpConf' + properties: { + subnet: { + id: '${vNetId}/subnets/AzureBastionSubnet' + } + publicIPAddress: { + id: !(empty(publicIPAddressId)) ? publicIPAddressId : publicIPAddress.outputs.resourceId + } + } + } + ] + } +} + +resource azureBastion_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureBastion.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureBastion +} + +resource azureBastion_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: azureBastion +} + +module azureBastion_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Bastion-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureBastion.id + } +}] + +@description('The resource group the Azure Bastion was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name the Azure Bastion') +output name string = azureBastion.name + +@description('The resource ID the Azure Bastion') +output resourceId string = azureBastion.id diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/readme.md b/carml/1.0.1/Microsoft.Network/bastionHosts/readme.md new file mode 100644 index 000000000..b0dd8761c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/readme.md @@ -0,0 +1,108 @@ +# Bastion Hosts `[Microsoft.Network/bastionHosts]` + +This module deploys a bastion host. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/bastionHosts` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Bastion resource | +| `vNetId` | string | Shared services Virtual Network resource identifier | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[BastionAuditLogs]` | `[BastionAuditLogs]` | Optional. The name of bastion logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicIPAddressId` | string | `''` | | Specifies the resource ID of the existing public IP to be leveraged by Azure Bastion. | +| `publicIPAddressObject` | object | `{object}` | | Specifies the properties of the public IP to create and be used by Azure Bastion. If it's not provided and publicIPAddressId is empty, a '-pip' suffix will be appended to the Bastion's name. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scaleUnits` | int | `2` | | The scale units for the Bastion Host resource. | +| `skuType` | string | `'Basic'` | `[Basic, Standard]` | The SKU of this Bastion Host. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name the Azure Bastion | +| `resourceGroupName` | string | The resource group the Azure Bastion was deployed into | +| `resourceId` | string | The resource ID the Azure Bastion | + +## Template references + +- [Bastionhosts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/bastionHosts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/bastionHosts/version.json b/carml/1.0.1/Microsoft.Network/bastionHosts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/bastionHosts/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/carml/1.0.1/Microsoft.Network/connections/.parameters/vnet2vnet.parameters.json b/carml/1.0.1/Microsoft.Network/connections/.parameters/vnet2vnet.parameters.json new file mode 100644 index 000000000..b1734ef61 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/connections/.parameters/vnet2vnet.parameters.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnetgwc-x-001" + }, + "virtualNetworkGateway1": { + "value": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworkGateways/<>-az-vnet-vpn-gw-p-001" + } + }, + "virtualNetworkGateway2": { + "value": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworkGateways/<>-az-vnet-vpn-gw-p-002" + } + }, + "vpnSharedKey": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "vpnSharedKey" + } + }, + "virtualNetworkGatewayConnectionType": { + "value": "Vnet2Vnet" + }, + "enableBgp": { + "value": false + }, + "location": { + "value": "eastus" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/connections/deploy.bicep b/carml/1.0.1/Microsoft.Network/connections/deploy.bicep new file mode 100644 index 000000000..cdf3fdaaa --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/connections/deploy.bicep @@ -0,0 +1,125 @@ +@description('Required. Remote connection name') +param name string + +@description('Optional. Specifies a VPN shared key. The same value has to be specified on both Virtual Network Gateways') +param vpnSharedKey string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Gateway connection type.') +@allowed([ + 'IPsec' + 'Vnet2Vnet' + 'ExpressRoute' + 'VPNClient' +]) +param virtualNetworkGatewayConnectionType string = 'IPsec' + +@description('Optional. Value to specify if BGP is enabled or not') +param enableBgp bool = false + +@description('Optional. Enable policy-based traffic selectors') +param usePolicyBasedTrafficSelectors bool = false + +@description('Optional. The IPSec Policies to be considered by this connection') +param customIPSecPolicy object = { + saLifeTimeSeconds: 0 + saDataSizeKilobytes: 0 + ipsecEncryption: '' + ipsecIntegrity: '' + ikeEncryption: '' + ikeIntegrity: '' + dhGroup: '' + pfsGroup: '' +} + +@description('Optional. The weight added to routes learned from this BGP speaker.') +param routingWeight int = -1 + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. The primary Virtual Network Gateway.') +param virtualNetworkGateway1 object + +@description('Optional. The remote Virtual Network Gateway. Used for connection type [Vnet2Vnet]') +param virtualNetworkGateway2 object = {} + +@description('Optional. The remote peer. Used for connection type [ExpressRoute]') +param peer object = {} + +@description('Optional. The local network gateway. Used for connection type [IPsec]') +param localNetworkGateway2 object = {} + +var customIPSecPolicy_var = [ + { + saLifeTimeSeconds: customIPSecPolicy.saLifeTimeSeconds + saDataSizeKilobytes: customIPSecPolicy.saDataSizeKilobytes + ipsecEncryption: customIPSecPolicy.ipsecEncryption + ipsecIntegrity: customIPSecPolicy.ipsecIntegrity + ikeEncryption: customIPSecPolicy.ikeEncryption + ikeIntegrity: customIPSecPolicy.ikeIntegrity + dhGroup: customIPSecPolicy.dhGroup + pfsGroup: customIPSecPolicy.pfsGroup + } +] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource connection 'Microsoft.Network/connections@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + connectionType: virtualNetworkGatewayConnectionType + virtualNetworkGateway1: virtualNetworkGateway1 + virtualNetworkGateway2: virtualNetworkGatewayConnectionType == 'Vnet2Vnet' ? virtualNetworkGateway2 : null + localNetworkGateway2: virtualNetworkGatewayConnectionType == 'Ipsec' ? localNetworkGateway2 : null + peer: virtualNetworkGatewayConnectionType == 'ExpressRoute' ? peer : null + sharedKey: virtualNetworkGatewayConnectionType != 'ExpressRoute' ? vpnSharedKey : null + usePolicyBasedTrafficSelectors: usePolicyBasedTrafficSelectors + ipsecPolicies: !empty(customIPSecPolicy.ipsecEncryption) ? customIPSecPolicy_var : customIPSecPolicy.ipsecEncryption + routingWeight: routingWeight != -1 ? routingWeight : null + enableBgp: enableBgp + } +} + +resource connection_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${connection.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: connection +} + +@description('The resource group the remote connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the remote connection') +output name string = connection.name + +@description('The resource ID of the remote connection') +output resourceId string = connection.id diff --git a/carml/1.0.1/Microsoft.Network/connections/readme.md b/carml/1.0.1/Microsoft.Network/connections/readme.md new file mode 100644 index 000000000..d4ca73abc --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/connections/readme.md @@ -0,0 +1,149 @@ +# Virtual Network Gateway Connections `[Microsoft.Network/connections]` + +This template deploys a virtual network gateway connection. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/connections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Remote connection name | +| `virtualNetworkGateway1` | object | The primary Virtual Network Gateway. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `customIPSecPolicy` | object | `{object}` | | The IPSec Policies to be considered by this connection | +| `enableBgp` | bool | `False` | | Value to specify if BGP is enabled or not | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `localNetworkGateway2` | object | `{object}` | | The local network gateway. Used for connection type [IPsec] | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `peer` | object | `{object}` | | The remote peer. Used for connection type [ExpressRoute] | +| `routingWeight` | int | `-1` | | The weight added to routes learned from this BGP speaker. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `usePolicyBasedTrafficSelectors` | bool | `False` | | Enable policy-based traffic selectors | +| `virtualNetworkGateway2` | object | `{object}` | | The remote Virtual Network Gateway. Used for connection type [Vnet2Vnet] | +| `virtualNetworkGatewayConnectionType` | string | `'IPsec'` | `[IPsec, Vnet2Vnet, ExpressRoute, VPNClient]` | Gateway connection type. | +| `vpnSharedKey` | string | `''` | | Specifies a VPN shared key. The same value has to be specified on both Virtual Network Gateways | + + +### Parameter Usage: `virtualNetworkGateway1` + +The primary virtual network gateway object. + +```json +"virtualNetworkGateway1" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/virtualNetworkGateways/myGateway01", +} +``` + +### Parameter Usage: `virtualNetworkGateway2` + +The secondary virtual network gateway used for VNET to VNET connections. + +```json +"virtualNetworkGateway2" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/virtualNetworkGateways/myGateway02"ss +} +``` + +### Parameter Usage: `localNetworkGateway2` + +The local virtual network gateway object. + +```json +"localNetworkGateway2" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/localNetworkGateways/myGateway" +} +``` + +### Parameter Usage: `peer` + +The remote peer object used for ExpressRoute connections + +```json +"peer" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/expressRouteCircuits/expressRoute" +} +``` + +### Parameter Usage: `customIPSecPolicy` + +If ipsecEncryption parameter is empty, customIPSecPolicy will not be deployed. The parameter file should look like below. + +```json +"customIPSecPolicy": { + "value": { + "saLifeTimeSeconds": 0, + "saDataSizeKilobytes": 0, + "ipsecEncryption": "", + "ipsecIntegrity": "", + "ikeEncryption": "", + "ikeIntegrity": "", + "dhGroup": "", + "pfsGroup": "" + } +}, +``` + +Format of the full customIPSecPolicy parameter in parameter file. + +```json +"customIPSecPolicy": { + "value": { + "saLifeTimeSeconds": 28800, + "saDataSizeKilobytes": 102400000, + "ipsecEncryption": "AES256", + "ipsecIntegrity": "SHA256", + "ikeEncryption": "AES256", + "ikeIntegrity": "SHA256", + "dhGroup": "DHGroup14", + "pfsGroup": "None" + } +}, +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the remote connection | +| `resourceGroupName` | string | The resource group the remote connection was deployed into | +| `resourceId` | string | The resource ID of the remote connection | + +## Template references + +- [Connections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/connections) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.1/Microsoft.Network/connections/version.json b/carml/1.0.1/Microsoft.Network/connections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/connections/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/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e350577b6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(ddosProtectionPlan.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: ddosProtectionPlan +}] diff --git a/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json new file mode 100644 index 000000000..3d697dee9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ddos-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/deploy.bicep b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/deploy.bicep new file mode 100644 index 000000000..ecd0083f4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/deploy.bicep @@ -0,0 +1,71 @@ +@description('Required. Name of the DDoS protection plan to assign the VNET to.') +@minLength(1) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource ddosProtectionPlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${ddosProtectionPlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: ddosProtectionPlan +} + +module ddosProtectionPlan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DDoSProtectionPlan-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: ddosProtectionPlan.id + } +}] + +@description('The resource group the DDOS protection plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the DDOS protection plan') +output resourceId string = ddosProtectionPlan.id + +@description('The name of the DDOS protection plan') +output name string = ddosProtectionPlan.name diff --git a/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/readme.md b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/readme.md new file mode 100644 index 000000000..0f2bd2762 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/readme.md @@ -0,0 +1,92 @@ +# DDoS Protection Plans `[Microsoft.Network/ddosProtectionPlans]` + +This template deploys a DDoS protection plan. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/ddosProtectionPlans` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | `''` | Name of the DDoS protection plan to assign the VNET to. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the DDOS protection plan | +| `resourceGroupName` | string | The resource group the DDOS protection plan was deployed into | +| `resourceId` | string | The resource ID of the DDOS protection plan | + +## Template references + +- [Ddosprotectionplans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/ddosProtectionPlans) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/version.json b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ddosProtectionPlans/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/carml/1.0.1/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..9136bdf8c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(expressRouteCircuits.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: expressRouteCircuits +}] diff --git a/carml/1.0.1/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json new file mode 100644 index 000000000..8050f4406 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-erc-x-001" + }, + "serviceProviderName": { + "value": "Equinix" + }, + "peeringLocation": { + "value": "Amsterdam" + }, + "bandwidthInMbps": { + "value": 50 + }, + "skuTier": { + "value": "Standard" + }, + "skuFamily": { + "value": "MeteredData" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/expressRouteCircuits/deploy.bicep b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/deploy.bicep new file mode 100644 index 000000000..fb217b5d0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/deploy.bicep @@ -0,0 +1,220 @@ +@description('Required. This is the name of the ExpressRoute circuit') +param name string + +@description('Required. This is the name of the ExpressRoute Service Provider. It must exactly match one of the Service Providers from List ExpressRoute Service Providers API call.') +param serviceProviderName string + +@description('Required. This is the name of the peering location and not the ARM resource location. It must exactly match one of the available peering locations from List ExpressRoute Service Providers API call.') +param peeringLocation string + +@description('Required. This is the bandwidth in Mbps of the circuit being created. It must exactly match one of the available bandwidth offers List ExpressRoute Service Providers API call.') +param bandwidthInMbps int + +@description('Required. Chosen SKU Tier of ExpressRoute circuit. Choose from Local, Premium or Standard SKU tiers.') +@allowed([ + 'Local' + 'Standard' + 'Premium' +]) +param skuTier string = 'Standard' + +@description('Required. Chosen SKU family of ExpressRoute circuit. Choose from MeteredData or UnlimitedData SKU families.') +@allowed([ + 'MeteredData' + 'UnlimitedData' +]) +param skuFamily string = 'MeteredData' + +@description('Optional. Enabled BGP peering type for the Circuit.') +@allowed([ + true + false +]) +param peering bool = false + +@description('Optional. BGP peering type for the Circuit. Choose from AzurePrivatePeering, AzurePublicPeering or MicrosoftPeering.') +@allowed([ + 'AzurePrivatePeering' + 'MicrosoftPeering' +]) +param peeringType string = 'AzurePrivatePeering' + +@description('Optional. The shared key for peering configuration. Router does MD5 hash comparison to validate the packets sent by BGP connection. This parameter is optional and can be removed from peering configuration if not required.') +param sharedKey string = '' + +@description('Optional. The autonomous system number of the customer/connectivity provider.') +param peerASN int = 0 + +@description('Optional. A /30 subnet used to configure IP addresses for interfaces on Link1.') +param primaryPeerAddressPrefix string = '' + +@description('Optional. A /30 subnet used to configure IP addresses for interfaces on Link2.') +param secondaryPeerAddressPrefix string = '' + +@description('Optional. Specifies the identifier that is used to identify the customer.') +param vlanId int = 0 + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'PeeringRouteLog' +]) +param diagnosticLogCategoriesToEnable array = [ + 'PeeringRouteLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var peeringConfiguration = [ + { + name: peeringType + properties: { + peeringType: peeringType + sharedKey: sharedKey + peerASN: peerASN + primaryPeerAddressPrefix: primaryPeerAddressPrefix + secondaryPeerAddressPrefix: secondaryPeerAddressPrefix + vlanId: vlanId + } + } +] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: '${skuTier}_${skuFamily}' + tier: skuTier + family: skuTier == 'Local' ? 'UnlimitedData' : skuFamily + } + properties: { + serviceProviderProperties: { + serviceProviderName: serviceProviderName + peeringLocation: peeringLocation + bandwidthInMbps: bandwidthInMbps + } + peerings: peering ? peeringConfiguration : null + } +} + +resource expressRouteCircuits_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${expressRouteCircuits.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: expressRouteCircuits +} + +resource expressRouteCircuits_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: expressRouteCircuits +} + +module expressRouteCircuits_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ExpRouteCircuits-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: expressRouteCircuits.id + } +}] + +@description('The resource ID of express route curcuit') +output resourceId string = expressRouteCircuits.id + +@description('The resource group the express route curcuit was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of express route curcuit') +output name string = expressRouteCircuits.name + +@description('The service key of the express route circuit') +output serviceKey string = reference(expressRouteCircuits.id, '2021-02-01').serviceKey diff --git a/carml/1.0.1/Microsoft.Network/expressRouteCircuits/readme.md b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/readme.md new file mode 100644 index 000000000..72bcf034d --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/readme.md @@ -0,0 +1,115 @@ +# ExpressRoute Circuits `[Microsoft.Network/expressRouteCircuits]` + +This template deploys an express route circuit. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/expressRouteCircuits` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `bandwidthInMbps` | int | | | This is the bandwidth in Mbps of the circuit being created. It must exactly match one of the available bandwidth offers List ExpressRoute Service Providers API call. | +| `name` | string | | | This is the name of the ExpressRoute circuit | +| `peeringLocation` | string | | | This is the name of the peering location and not the ARM resource location. It must exactly match one of the available peering locations from List ExpressRoute Service Providers API call. | +| `serviceProviderName` | string | | | This is the name of the ExpressRoute Service Provider. It must exactly match one of the Service Providers from List ExpressRoute Service Providers API call. | +| `skuFamily` | string | `'MeteredData'` | `[MeteredData, UnlimitedData]` | Chosen SKU family of ExpressRoute circuit. Choose from MeteredData or UnlimitedData SKU families. | +| `skuTier` | string | `'Standard'` | `[Local, Standard, Premium]` | Chosen SKU Tier of ExpressRoute circuit. Choose from Local, Premium or Standard SKU tiers. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[PeeringRouteLog]` | `[PeeringRouteLog]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `peerASN` | int | `0` | | The autonomous system number of the customer/connectivity provider. | +| `peering` | bool | `False` | `[True, False]` | Enabled BGP peering type for the Circuit. | +| `peeringType` | string | `'AzurePrivatePeering'` | `[AzurePrivatePeering, MicrosoftPeering]` | BGP peering type for the Circuit. Choose from AzurePrivatePeering, AzurePublicPeering or MicrosoftPeering. | +| `primaryPeerAddressPrefix` | string | `''` | | A /30 subnet used to configure IP addresses for interfaces on Link1. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `secondaryPeerAddressPrefix` | string | `''` | | A /30 subnet used to configure IP addresses for interfaces on Link2. | +| `sharedKey` | string | `''` | | The shared key for peering configuration. Router does MD5 hash comparison to validate the packets sent by BGP connection. This parameter is optional and can be removed from peering configuration if not required. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `vlanId` | int | `0` | | Specifies the identifier that is used to identify the customer. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of express route curcuit | +| `resourceGroupName` | string | The resource group the express route curcuit was deployed into | +| `resourceId` | string | The resource ID of express route curcuit | +| `serviceKey` | string | The service key of the express route circuit | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Expressroutecircuits](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/expressRouteCircuits) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/expressRouteCircuits/version.json b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/expressRouteCircuits/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/carml/1.0.1/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json new file mode 100644 index 000000000..bb555089e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fwpol-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/firewallPolicies/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/firewallPolicies/.parameters/parameters.json new file mode 100644 index 000000000..67e03ad34 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fwpol-x-002" + }, + "ruleCollectionGroups": { + "value": [ + { + "name": "<>-rule-001", + "priority": 5000, + "ruleCollections": [ + { + "name": "collection002", + "priority": 5555, + "action": { + "type": "Allow" + }, + "rules": [ + { + "name": "rule002", + "ipProtocols": [ + "TCP", + "UDP" + ], + "destinationPorts": [ + "80" + ], + "sourceAddresses": [ + "*" + ], + "sourceIpGroups": [], + "ruleType": "NetworkRule", + "destinationIpGroups": [], + "destinationAddresses": [ + "*" + ], + "destinationFqdns": [] + } + ], + "ruleCollectionType": "FirewallPolicyFilterRuleCollection" + } + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/firewallPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Network/firewallPolicies/deploy.bicep new file mode 100644 index 000000000..eb9e0c3e9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/deploy.bicep @@ -0,0 +1,173 @@ +@description('Required. Name of the Firewall Policy.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Firewall policy resource.') +param tags object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Resource ID of the base policy.') +param basePolicyResourceId string = '' + +@description('Optional. Enable DNS Proxy on Firewalls attached to the Firewall Policy.') +param enableProxy bool = false + +@description('Optional. List of Custom DNS Servers.') +param servers array = [] + +@description('Optional. A flag to indicate if the insights are enabled on the policy.') +param insightsIsEnabled bool = false + +@description('Optional. Default Log Analytics Resource ID for Firewall Policy Insights.') +param defaultWorkspaceId string = '' + +@description('Optional. List of workspaces for Firewall Policy Insights.') +param workspaces array = [] + +@description('Optional. Number of days the insights should be enabled on the policy.') +param retentionDays int = 365 + +@description('Optional. List of rules for traffic to bypass.') +param bypassTrafficSettings array = [] + +@description('Optional. List of specific signatures states.') +param signatureOverrides array = [] + +@description('Optional. The configuring of intrusion detection.') +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +param mode string = 'Off' + +@description('Optional. Tier of Firewall Policy.') +@allowed([ + 'Premium' + 'Standard' +]) +param tier string = 'Standard' + +@description('Optional. List of private IP addresses/IP address ranges to not be SNAT.') +param privateRanges array = [] + +@description('Optional. The operation mode for Threat Intel.') +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +param threatIntelMode string = 'Off' + +@description('Optional. List of FQDNs for the ThreatIntel Allowlist.') +param fqdns array = [] + +@description('Optional. List of IP addresses for the ThreatIntel Allowlist.') +param ipAddresses array = [] + +@description('Optional. Secret ID of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault. ') +param keyVaultSecretId string = '' + +@description('Optional. Name of the CA certificate.') +param certificateName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Rule collection groups.') +param ruleCollectionGroups array = [] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + basePolicy: !empty(basePolicyResourceId) ? { + id: basePolicyResourceId + } : null + dnsSettings: enableProxy ? { + enableProxy: enableProxy + servers: servers + } : null + insights: insightsIsEnabled ? { + isEnabled: insightsIsEnabled + logAnalyticsResources: { + defaultWorkspaceId: { + id: !empty(defaultWorkspaceId) ? defaultWorkspaceId : null + } + workspaces: !empty(workspaces) ? workspaces : null + } + retentionDays: retentionDays + } : null + intrusionDetection: (mode != 'Off') ? { + configuration: { + bypassTrafficSettings: !empty(bypassTrafficSettings) ? bypassTrafficSettings : null + signatureOverrides: !empty(signatureOverrides) ? signatureOverrides : null + } + mode: mode + } : null + sku: { + tier: tier + } + snat: !empty(privateRanges) ? { + privateRanges: privateRanges + } : null + threatIntelMode: threatIntelMode + threatIntelWhitelist: { + fqdns: fqdns + ipAddresses: ipAddresses + } + transportSecurity: (!empty(keyVaultSecretId) || !empty(certificateName)) ? { + certificateAuthority: { + keyVaultSecretId: !empty(keyVaultSecretId) ? keyVaultSecretId : null + name: !empty(certificateName) ? certificateName : null + } + } : null + } +} + +module firewallPolicy_ruleCollectionGroups 'ruleCollectionGroups/deploy.bicep' = [for (ruleCollectionGroup, index) in ruleCollectionGroups: { + name: '${uniqueString(deployment().name, location)}-firewallPolicy_ruleCollectionGroups-${index}' + params: { + firewallPolicyName: firewallPolicy.name + name: ruleCollectionGroup.name + priority: ruleCollectionGroup.priority + ruleCollections: ruleCollectionGroup.ruleCollections + } +}] + +@description('The name of the deployed firewall policy') +output name string = firewallPolicy.name + +@description('The resource ID of the deployed firewall policy') +output resourceId string = firewallPolicy.id + +@description('The resource group of the deployed firewall policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/firewallPolicies/readme.md b/carml/1.0.1/Microsoft.Network/firewallPolicies/readme.md new file mode 100644 index 000000000..108bb0dec --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/readme.md @@ -0,0 +1,95 @@ +# Firewall Policies `[Microsoft.Network/firewallPolicies]` + +This module deploys Firewall Policies. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies` | 2021-05-01 | +| `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Firewall Policy. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `basePolicyResourceId` | string | `''` | | Resource ID of the base policy. | +| `bypassTrafficSettings` | array | `[]` | | List of rules for traffic to bypass. | +| `certificateName` | string | `''` | | Name of the CA certificate. | +| `defaultWorkspaceId` | string | `''` | | Default Log Analytics Resource ID for Firewall Policy Insights. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableProxy` | bool | `False` | | Enable DNS Proxy on Firewalls attached to the Firewall Policy. | +| `fqdns` | array | `[]` | | List of FQDNs for the ThreatIntel Allowlist. | +| `insightsIsEnabled` | bool | `False` | | A flag to indicate if the insights are enabled on the policy. | +| `ipAddresses` | array | `[]` | | List of IP addresses for the ThreatIntel Allowlist. | +| `keyVaultSecretId` | string | `''` | | Secret ID of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `mode` | string | `'Off'` | `[Alert, Deny, Off]` | The configuring of intrusion detection. | +| `privateRanges` | array | `[]` | | List of private IP addresses/IP address ranges to not be SNAT. | +| `retentionDays` | int | `365` | | Number of days the insights should be enabled on the policy. | +| `ruleCollectionGroups` | _[ruleCollectionGroups](ruleCollectionGroups/readme.md)_ array | `[]` | | Rule collection groups. | +| `servers` | array | `[]` | | List of Custom DNS Servers. | +| `signatureOverrides` | array | `[]` | | List of specific signatures states. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the Firewall policy resource. | +| `threatIntelMode` | string | `'Off'` | `[Alert, Deny, Off]` | The operation mode for Threat Intel. | +| `tier` | string | `'Standard'` | `[Premium, Standard]` | Tier of Firewall Policy. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `workspaces` | array | `[]` | | List of workspaces for Firewall Policy Insights. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed firewall policy | +| `resourceGroupName` | string | The resource group of the deployed firewall policy | +| `resourceId` | string | The resource ID of the deployed firewall policy | + +## Template references + +- [Firewallpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies) +- [Firewallpolicies/Rulecollectiongroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies/ruleCollectionGroups) diff --git a/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep b/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep new file mode 100644 index 000000000..bdf4650cc --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. Name of the Firewall Policy.') +param firewallPolicyName string + +@description('Required. The name of the rule collection group to deploy') +param name string + +@description('Required. Priority of the Firewall Policy Rule Collection Group resource.') +param priority int + +@description('Optional. Group of Firewall Policy rule collections.') +param ruleCollections array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' existing = { + name: firewallPolicyName +} + +resource ruleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2021-05-01' = { + name: name + parent: firewallPolicy + properties: { + priority: priority + ruleCollections: ruleCollections + } +} + +@description('The name of the deployed rule collection group') +output name string = ruleCollectionGroup.name + +@description('The resource ID of the deployed rule collection group') +output resourceId string = ruleCollectionGroup.id + +@description('The resource group of the deployed rule collection group') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md b/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md new file mode 100644 index 000000000..702b54bd7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md @@ -0,0 +1,59 @@ +# Network Firewall Policies Rule Collection Groups `[Microsoft.Network/firewallPolicies/ruleCollectionGroups]` + +This module deploys Network Firewall Policies Rule Collection Groups. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `firewallPolicyName` | string | Name of the Firewall Policy. | +| `name` | string | The name of the rule collection group to deploy | +| `priority` | int | Priority of the Firewall Policy Rule Collection Group resource. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ruleCollections` | array | `[]` | Group of Firewall Policy rule collections. | + + +### Parameter Usage: `ruleCollections` + +For remaining properties, see [FirewallPolicyRuleCollection objects](https://docs.microsoft.com/en-us/azure/templates/microsoft.network/firewallpolicies/rulecollectiongroups?tabs=json#firewallpolicyrulecollection-objects) + +```json +"ruleCollections": [ + { + "name": "string", + "priority": "int", + "ruleCollectionType": "string" + // For remaining properties, see FirewallPolicyRuleCollection objects + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed rule collection group | +| `resourceGroupName` | string | The resource group of the deployed rule collection group | +| `resourceId` | string | The resource ID of the deployed rule collection group | + +## Template references + +- [Firewallpolicies/Rulecollectiongroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies/ruleCollectionGroups) diff --git a/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/version.json b/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/ruleCollectionGroups/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/carml/1.0.1/Microsoft.Network/firewallPolicies/version.json b/carml/1.0.1/Microsoft.Network/firewallPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/firewallPolicies/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/carml/1.0.1/Microsoft.Network/frontDoors/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/frontDoors/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c96e0a3bb --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/frontDoors/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource frontDoor 'Microsoft.Network/frontDoors@2020-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(frontDoor.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: frontDoor +}] diff --git a/carml/1.0.1/Microsoft.Network/frontDoors/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/frontDoors/.parameters/parameters.json new file mode 100644 index 000000000..60be79daa --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/frontDoors/.parameters/parameters.json @@ -0,0 +1,112 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fd-x-001" + }, + "backendPools": { + "value": [ + { + "name": "backendPool", + "properties": { + "backends": [ + { + "address": "biceptest.local", + "backendHostHeader": "backendAddress", + "httpPort": 80, + "httpsPort": 443, + "weight": 50, + "priority": 1, + "enabledState": "Enabled", + "privateLinkAlias": "", + "privateLinkApprovalMessage": "", + "privateLinkLocation": "", + "privateLinkResourceId": "" + } + ], + "LoadBalancingSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/LoadBalancingSettings/loadBalancer" + }, + "HealthProbeSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/HealthProbeSettings/heathProbe" + } + } + } + ] + }, + "enforceCertificateNameCheck": { + "value": "Disabled" + }, + "sendRecvTimeoutSeconds": { + "value": 10 + }, + "frontendEndpoints": { + "value": [ + { + "name": "frontEnd", + "properties": { + "hostName": "<>-az-fd-x-001.azurefd.net", + "sessionAffinityEnabledState": "Disabled", + "sessionAffinityTtlSeconds": 60 + } + } + ] + }, + "healthProbeSettings": { + "value": [ + { + "name": "heathProbe", + "properties": { + "enabledState": "", + "healthProbeMethod": "", + "intervalInSeconds": 60, + "path": "/", + "protocol": "Https" + } + } + ] + }, + "loadBalancingSettings": { + "value": [ + { + "name": "loadBalancer", + "properties": { + "additionalLatencyMilliseconds": 0, + "sampleSize": 50, + "successfulSamplesRequired": 1 + } + } + ] + }, + "routingRules": { + "value": [ + { + "name": "routingRule", + "properties": { + "acceptedProtocols": [ + "Http", + "Https" + ], + "enabledState": "Enabled", + "frontendEndpoints": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/FrontendEndpoints/frontEnd" + } + ], + "patternsToMatch": [ + "/*" + ], + "routeConfiguration": { + "@odata.type": "#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration", + "forwardingProtocol": "MatchRequest", + "backendPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/BackendPools/backendPool" + } + } + } + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/frontDoors/deploy.bicep b/carml/1.0.1/Microsoft.Network/frontDoors/deploy.bicep new file mode 100644 index 000000000..ed615578a --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/frontDoors/deploy.bicep @@ -0,0 +1,178 @@ +@description('Required. The name of the frontDoor.') +@minLength(1) +@maxLength(64) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. Backend address pool of the frontdoor resource.') +param backendPools array = [] + +@description('Optional. Enforce certificate name check of the frontdoor resource.') +param enforceCertificateNameCheck string = 'Disabled' + +@description('Optional. Certificate name check time of the frontdoor resource.') +param sendRecvTimeoutSeconds int = 600 + +@description('Required. State of the frontdoor resource.') +param enabledState string = 'Enabled' + +@description('Required. Friendly name of the frontdoor resource.') +param friendlyName string = '' + +@description('Required. Frontend endpoints of the frontdoor resource.') +param frontendEndpoints array = [] + +@description('Required. Heath probe settings of the frontdoor resource.') +param healthProbeSettings array = [] + +@description('Required. Load balancing settings of the frontdoor resource.') +param loadBalancingSettings array = [] + +@description('Required. Routing rules settings of the frontdoor resource.') +param routingRules array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'FrontdoorAccessLog' + 'FrontdoorWebApplicationFirewallLog' +]) +param logsToEnable array = [ + 'FrontdoorAccessLog' + 'FrontdoorWebApplicationFirewallLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource frontDoor 'Microsoft.Network/frontDoors@2020-05-01' = { + name: name + location: 'global' + tags: tags + properties: { + backendPools: backendPools + backendPoolsSettings: { + enforceCertificateNameCheck: enforceCertificateNameCheck + sendRecvTimeoutSeconds: sendRecvTimeoutSeconds + } + enabledState: enabledState + friendlyName: friendlyName + frontendEndpoints: frontendEndpoints + healthProbeSettings: healthProbeSettings + loadBalancingSettings: loadBalancingSettings + routingRules: routingRules + } +} + +resource frontDoor_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${frontDoor.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: frontDoor +} + +resource frontDoor_diagnosticSettingName 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${frontDoor.name}-diagnosticSettings' + properties: { + storageAccountId: empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId + workspaceId: empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId + eventHubAuthorizationRuleId: empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId + eventHubName: empty(diagnosticEventHubName) ? null : diagnosticEventHubName + metrics: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsMetrics + logs: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsLogs + } + scope: frontDoor +} + +module frontDoor_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: frontDoor.id + } +}] + +@description('The name of the front door') +output name string = frontDoor.name + +@description('The resource ID of the front door') +output resourceId string = frontDoor.id + +@description('The resource group the front door was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/frontDoors/readme.md b/carml/1.0.1/Microsoft.Network/frontDoors/readme.md new file mode 100644 index 000000000..ef8e5057f --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/frontDoors/readme.md @@ -0,0 +1,111 @@ +# Front Doors `[Microsoft.Network/frontDoors]` + +This module deploys Front Doors. + + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/frontDoors` | 2020-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `backendPools` | array | `[]` | Backend address pool of the frontdoor resource. | +| `enabledState` | string | `'Enabled'` | State of the frontdoor resource. | +| `friendlyName` | string | `''` | Friendly name of the frontdoor resource. | +| `frontendEndpoints` | array | `[]` | Frontend endpoints of the frontdoor resource. | +| `healthProbeSettings` | array | `[]` | Heath probe settings of the frontdoor resource. | +| `loadBalancingSettings` | array | `[]` | Load balancing settings of the frontdoor resource. | +| `name` | string | | The name of the frontDoor. | +| `routingRules` | array | `[]` | Routing rules settings of the frontdoor resource. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforceCertificateNameCheck` | string | `'Disabled'` | | Enforce certificate name check of the frontdoor resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `logsToEnable` | array | `[FrontdoorAccessLog, FrontdoorWebApplicationFirewallLog]` | `[FrontdoorAccessLog, FrontdoorWebApplicationFirewallLog]` | The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sendRecvTimeoutSeconds` | int | `600` | | Certificate name check time of the frontdoor resource. | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the front door | +| `resourceGroupName` | string | The resource group the front door was deployed into | +| `resourceId` | string | The resource ID of the front door | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Frontdoors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-05-01/frontDoors) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/frontDoors/version.json b/carml/1.0.1/Microsoft.Network/frontDoors/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/frontDoors/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d6255df11 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource ipGroup 'Microsoft.Network/ipGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(ipGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: ipGroup +}] diff --git a/carml/1.0.1/Microsoft.Network/ipGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/ipGroups/.parameters/parameters.json new file mode 100644 index 000000000..88c2f5a13 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ipGroups/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "iacsGroup-servers" + }, + "ipAddresses": { + "value": [ + "10.0.0.1", + "10.0.0.2" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/ipGroups/deploy.bicep b/carml/1.0.1/Microsoft.Network/ipGroups/deploy.bicep new file mode 100644 index 000000000..ee21e30c1 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ipGroups/deploy.bicep @@ -0,0 +1,76 @@ +@description('Required. The name of the ipGroups.') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. IpAddresses/IpAddressPrefixes in the IpGroups resource.') +param ipAddresses array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource ipGroup 'Microsoft.Network/ipGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipAddresses: ipAddresses + } +} + +resource ipGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${ipGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: ipGroup +} + +module ipGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-IPGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: ipGroup.id + } +}] + +@description('The resource ID of the IP group') +output resourceId string = ipGroup.id + +@description('The resource group of the IP group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the IP group') +output name string = ipGroup.name diff --git a/carml/1.0.1/Microsoft.Network/ipGroups/readme.md b/carml/1.0.1/Microsoft.Network/ipGroups/readme.md new file mode 100644 index 000000000..e1d5a45cb --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ipGroups/readme.md @@ -0,0 +1,93 @@ +# IP Groups `[Microsoft.Network/ipGroups]` + +This module deploys an IP group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/ipGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the ipGroups. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipAddresses` | array | `[]` | | IpAddresses/IpAddressPrefixes in the IpGroups resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the IP group | +| `resourceGroupName` | string | The resource group of the IP group was deployed into | +| `resourceId` | string | The resource ID of the IP group | + +## Template references + +- [Ipgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/ipGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/ipGroups/version.json b/carml/1.0.1/Microsoft.Network/ipGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/ipGroups/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/carml/1.0.1/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..470e13b66 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(loadBalancer.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: loadBalancer +}] diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/internal.parameters.json b/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/internal.parameters.json new file mode 100644 index 000000000..4c3ffb022 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/internal.parameters.json @@ -0,0 +1,101 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-internal-001" + }, + "loadBalancerSku": { + "value": "Standard" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "privateIPConfig1", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + } + ] + }, + "backendAddressPools": { + "value": [ + { + "name": "servers" + } + ] + }, + "probes": { + "value": [ + { + "name": "probe1", + "protocol": "Tcp", + "port": "62000", + "intervalInSeconds": 5, + "numberOfProbes": 2 + } + ] + }, + "loadBalancingRules": { + "value": [ + { + "name": "privateIPLBRule1", + "frontendIPConfigurationName": "privateIPConfig1", + "frontendPort": 0, + "backendPort": 0, + "enableFloatingIP": true, + "idleTimeoutInMinutes": 4, + "protocol": "All", + "loadDistribution": "Default", + "probeName": "probe1", + "disableOutboundSnat": true, + "enableTcpReset": false, + "backendAddressPoolName": "servers" + } + ] + }, + "inboundNatRules": { + "value": [ + { + "name": "inboundNatRule1", + "frontendIPConfigurationName": "privateIPConfig1", + "frontendPort": 443, + "backendPort": 443, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 4, + "protocol": "Tcp", + "enableTcpReset": false + }, + { + "name": "inboundNatRule2", + "frontendIPConfigurationName": "privateIPConfig1", + "frontendPort": 3389, + "backendPort": 3389 + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/min.parameters.json new file mode 100644 index 000000000..695027dc9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/min.parameters.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-min-001" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "publicIPConfig1", + "publicIPAddressId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-min-lb" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/parameters.json new file mode 100644 index 000000000..8ed786238 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/.parameters/parameters.json @@ -0,0 +1,126 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-x-001" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "publicIPConfig1", + "publicIPAddressId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-lb" + } + ] + }, + "backendAddressPools": { + "value": [ + { + "name": "backendAddressPool1" + }, + { + "name": "backendAddressPool2" + } + ] + }, + "loadBalancingRules": { + "value": [ + { + "name": "publicIPLBRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 80, + "backendPort": 80, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "protocol": "Tcp", + "enableTcpReset": false, + "loadDistribution": "Default", + "disableOutboundSnat": true, + "probeName": "probe1", + "backendAddressPoolName": "backendAddressPool1" + }, + { + "name": "publicIPLBRule2", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 8080, + "backendPort": 8080, + "loadDistribution": "Default", + "probeName": "probe2", + "backendAddressPoolName": "backendAddressPool2" + } + ] + }, + "inboundNatRules": { + "value": [ + { + "name": "inboundNatRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 443, + "backendPort": 443, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 4, + "protocol": "Tcp", + "enableTcpReset": false + }, + { + "name": "inboundNatRule2", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 3389, + "backendPort": 3389 + } + ] + }, + "outboundRules": { + "value": [ + { + "name": "outboundRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "backendAddressPoolName": "backendAddressPool1", + "allocatedOutboundPorts": 63984 + } + ] + }, + "probes": { + "value": [ + { + "name": "probe1", + "protocol": "Tcp", + "port": 80, + "intervalInSeconds": 10, + "numberOfProbes": 5 + }, + { + "name": "probe2", + "protocol": "Https", + "port": 443, + "requestPath": "/" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep b/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep new file mode 100644 index 000000000..fa6d17707 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. The name of the parent load balancer') +param loadBalancerName string + +@description('Required. The name of the backend address pool') +param name string + +@description('Optional. An array of backend addresses.') +param loadBalancerBackendAddresses array = [] + +@description('Optional. An array of gateway load balancer tunnel interfaces.') +param tunnelInterfaces array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: loadBalancerName +} + +resource backendAddressPool 'Microsoft.Network/loadBalancers/backendAddressPools@2021-05-01' = { + name: name + properties: { + loadBalancerBackendAddresses: loadBalancerBackendAddresses + tunnelInterfaces: tunnelInterfaces + } + parent: loadBalancer +} + +@description('The name of the backend address pool') +output name string = backendAddressPool.name + +@description('The resource ID of the backend address pool') +output resourceId string = backendAddressPool.id + +@description('The resource group the backend address pool was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/readme.md b/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/readme.md new file mode 100644 index 000000000..ccaebf96f --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/readme.md @@ -0,0 +1,44 @@ +# Load Balancers Backend Address Pools `[Microsoft.Network/loadBalancers/backendAddressPools]` + +This module deploys load balancer backend address pools. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/loadBalancers/backendAddressPools` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `loadBalancerName` | string | The name of the parent load balancer | +| `name` | string | The name of the backend address pool | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `loadBalancerBackendAddresses` | array | `[]` | An array of backend addresses. | +| `tunnelInterfaces` | array | `[]` | An array of gateway load balancer tunnel interfaces. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backend address pool | +| `resourceGroupName` | string | The resource group the backend address pool was deployed into | +| `resourceId` | string | The resource ID of the backend address pool | + +## Template references + +- [Loadbalancers/Backendaddresspools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/backendAddressPools) diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/version.json b/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/backendAddressPools/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/carml/1.0.1/Microsoft.Network/loadBalancers/deploy.bicep b/carml/1.0.1/Microsoft.Network/loadBalancers/deploy.bicep new file mode 100644 index 000000000..8b324968d --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/deploy.bicep @@ -0,0 +1,266 @@ +@description('Required. The Proximity Placement Groups Name') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Name of a load balancer SKU.') +@allowed([ + 'Basic' + 'Standard' +]) +param loadBalancerSku string = 'Standard' + +@description('Required. Array of objects containing all frontend IP configurations') +@minLength(1) +param frontendIPConfigurations array + +@description('Optional. Collection of backend address pools used by a load balancer.') +param backendAddressPools array = [] + +@description('Optional. Array of objects containing all load balancing rules') +param loadBalancingRules array = [] + +@description('Optional. Array of objects containing all probes, these are references in the load balancing rules') +param probes array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Collection of inbound NAT Rules used by a load balancer. Defining inbound NAT rules on your load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. They have to reference individual inbound NAT rules.') +param inboundNatRules array = [] + +@description('Optional. The outbound rules.') +param outboundRules array = [] + +var frontendIPConfigurations_var = [for (frontendIPConfiguration, index) in frontendIPConfigurations: { + name: frontendIPConfiguration.name + properties: { + subnet: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) ? { + id: frontendIPConfiguration.subnetId + } : null + publicIPAddress: contains(frontendIPConfiguration, 'publicIPAddressId') && !empty(frontendIPConfiguration.publicIPAddressId) ? { + id: frontendIPConfiguration.publicIPAddressId + } : null + privateIPAddress: contains(frontendIPConfiguration, 'privateIPAddress') && !empty(frontendIPConfiguration.privateIPAddress) ? frontendIPConfiguration.privateIPAddress : null + privateIPAddressVersion: contains(frontendIPConfiguration, 'privateIPAddressVersion') ? frontendIPConfiguration.privateIPAddressVersion : 'IPv4' + privateIPAllocationMethod: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) ? (contains(frontendIPConfiguration, 'privateIPAddress') ? 'Static' : 'Dynamic') : null + gatewayLoadBalancer: contains(frontendIPConfiguration, 'gatewayLoadBalancer') && !empty(frontendIPConfiguration.gatewayLoadBalancer) ? { + id: frontendIPConfiguration.gatewayLoadBalancer + } : null + publicIPPrefix: contains(frontendIPConfiguration, 'publicIPPrefix') && !empty(frontendIPConfiguration.publicIPPrefix) ? { + id: frontendIPConfiguration.publicIPPrefix + } : null + } +}] + +var loadBalancingRules_var = [for loadBalancingRule in loadBalancingRules: { + name: loadBalancingRule.name + properties: { + backendAddressPool: { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, loadBalancingRule.backendAddressPoolName) + } + backendPort: loadBalancingRule.backendPort + disableOutboundSnat: contains(loadBalancingRule, 'disableOutboundSnat') ? loadBalancingRule.disableOutboundSnat : true + enableFloatingIP: contains(loadBalancingRule, 'enableFloatingIP') ? loadBalancingRule.enableFloatingIP : false + enableTcpReset: contains(loadBalancingRule, 'enableTcpReset') ? loadBalancingRule.enableTcpReset : false + frontendIPConfiguration: { + id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, loadBalancingRule.frontendIPConfigurationName) + } + frontendPort: loadBalancingRule.frontendPort + idleTimeoutInMinutes: contains(loadBalancingRule, 'idleTimeoutInMinutes') ? loadBalancingRule.idleTimeoutInMinutes : 4 + loadDistribution: contains(loadBalancingRule, 'loadDistribution') ? loadBalancingRule.loadDistribution : 'Default' + probe: { + id: '${az.resourceId('Microsoft.Network/loadBalancers', name)}/probes/${loadBalancingRule.probeName}' + } + protocol: contains(loadBalancingRule, 'protocol') ? loadBalancingRule.protocol : 'Tcp' + } +}] + +var outboundRules_var = [for outboundRule in outboundRules: { + name: outboundRule.name + properties: { + frontendIPConfigurations: [ + { + id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, outboundRule.frontendIPConfigurationName) + } + ] + backendAddressPool: { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, outboundRule.backendAddressPoolName) + } + protocol: contains(outboundRule, 'protocol') ? outboundRule.protocol : 'All' + allocatedOutboundPorts: contains(outboundRule, 'allocatedOutboundPorts') ? outboundRule.allocatedOutboundPorts : 63984 + enableTcpReset: contains(outboundRule, 'enableTcpReset') ? outboundRule.enableTcpReset : true + idleTimeoutInMinutes: contains(outboundRule, 'idleTimeoutInMinutes') ? outboundRule.idleTimeoutInMinutes : 4 + } +}] + +var probes_var = [for probe in probes: { + name: probe.name + properties: { + protocol: contains(probe, 'protocol') ? probe.protocol : 'Tcp' + requestPath: toLower(probe.protocol) != 'tcp' ? probe.requestPath : null + port: contains(probe, 'port') ? probe.port : 80 + intervalInSeconds: contains(probe, 'intervalInSeconds') ? probe.intervalInSeconds : 5 + numberOfProbes: contains(probe, 'numberOfProbes') ? probe.numberOfProbes : 2 + } +}] + +var backendAddressPoolNames = [for backendAddressPool in backendAddressPools: { + name: backendAddressPool.name +}] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: loadBalancerSku + } + properties: { + frontendIPConfigurations: frontendIPConfigurations_var + loadBalancingRules: loadBalancingRules_var + backendAddressPools: backendAddressPoolNames + outboundRules: outboundRules_var + probes: probes_var + } +} + +module loadBalancer_backendAddressPools 'backendAddressPools/deploy.bicep' = [for (backendAddressPool, index) in backendAddressPools: { + name: '${uniqueString(deployment().name, location)}-loadBalancer-backendAddressPools-${index}' + params: { + loadBalancerName: loadBalancer.name + name: backendAddressPool.name + tunnelInterfaces: contains(backendAddressPool, 'tunnelInterfaces') && !empty(backendAddressPool.tunnelInterfaces) ? backendAddressPool.tunnelInterfaces : [] + loadBalancerBackendAddresses: contains(backendAddressPool, 'loadBalancerBackendAddresses') && !empty(backendAddressPool.loadBalancerBackendAddresses) ? backendAddressPool.loadBalancerBackendAddresses : [] + } +}] + +module loadBalancer_inboundNATRules 'inboundNatRules/deploy.bicep' = [for (inboundNATRule, index) in inboundNatRules: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-inboundNatRules-${index}' + params: { + loadBalancerName: loadBalancer.name + name: inboundNATRule.name + frontendIPConfigurationName: inboundNATRule.frontendIPConfigurationName + frontendPort: inboundNATRule.frontendPort + backendPort: contains(inboundNATRule, 'backendPort') ? inboundNATRule.backendPort : inboundNATRule.frontendPort + backendAddressPoolName: contains(inboundNATRule, 'backendAddressPoolName') ? inboundNATRule.backendAddressPoolName : '' + enableFloatingIP: contains(inboundNATRule, 'enableFloatingIP') ? inboundNATRule.enableFloatingIP : false + enableTcpReset: contains(inboundNATRule, 'enableTcpReset') ? inboundNATRule.enableTcpReset : false + frontendPortRangeEnd: contains(inboundNATRule, 'frontendPortRangeEnd') ? inboundNATRule.frontendPortRangeEnd : -1 + frontendPortRangeStart: contains(inboundNATRule, 'frontendPortRangeStart') ? inboundNATRule.frontendPortRangeStart : -1 + idleTimeoutInMinutes: contains(inboundNATRule, 'idleTimeoutInMinutes') ? inboundNATRule.idleTimeoutInMinutes : 4 + protocol: contains(inboundNATRule, 'protocol') ? inboundNATRule.protocol : 'Tcp' + } + dependsOn: [ + loadBalancer_backendAddressPools + ] +}] + +resource loadBalancer_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${loadBalancer.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: loadBalancer +} + +resource loadBalancer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: loadBalancer +} + +module loadBalancer_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: loadBalancer.id + } +}] + +@description('The name of the load balancer') +output name string = loadBalancer.name + +@description('The resource ID of the load balancer') +output resourceId string = loadBalancer.id + +@description('The resource group the load balancer was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The backend address pools available in the load balancer.') +output backendpools array = loadBalancer.properties.backendAddressPools diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep b/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep new file mode 100644 index 000000000..1722a0f57 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep @@ -0,0 +1,97 @@ +@description('Required. The name of the parent load balancer') +param loadBalancerName string + +@description('Required. The name of the inbound NAT rule') +param name string + +@description('Required. The port for the external endpoint. Port numbers for each rule must be unique within the Load Balancer. ') +@minValue(1) +@maxValue(65534) +param frontendPort int + +@description('Optional. The port used for the internal endpoint.') +@minValue(1) +@maxValue(65535) +param backendPort int = frontendPort + +@description('Optional. Name of the backend address pool') +param backendAddressPoolName string = '' + +@description('Optional. Configures a virtual machine\'s endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. This setting can\'t be changed after you create the endpoint.') +param enableFloatingIP bool = false + +@description('Optional. Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. This element is only used when the protocol is set to TCP.') +param enableTcpReset bool = false + +@description('Required. The name of the frontend IP address to set for the inbound NAT rule') +param frontendIPConfigurationName string + +@description('Optional. The port range end for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeStart. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool.') +@minValue(-1) +@maxValue(65534) +param frontendPortRangeEnd int = -1 + +@description('Optional. The port range start for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeEnd. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool.') +@minValue(-1) +@maxValue(65534) +param frontendPortRangeStart int = -1 + +@description('Optional. The timeout for the TCP idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP.') +param idleTimeoutInMinutes int = 4 + +@description('Optional. The transport protocol for the endpoint.') +@allowed([ + 'All' + 'Tcp' + 'Udp' +]) +param protocol string = 'Tcp' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: loadBalancerName +} + +resource inboundNatRule 'Microsoft.Network/loadBalancers/inboundNatRules@2021-05-01' = { + name: name + properties: { + frontendPort: frontendPort + backendPort: backendPort + backendAddressPool: !empty(backendAddressPoolName) ? { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, backendAddressPoolName) + } : null + enableFloatingIP: enableFloatingIP + enableTcpReset: enableTcpReset + frontendIPConfiguration: { + id: '${loadBalancer.id}/frontendIPConfigurations/${frontendIPConfigurationName}' + } + frontendPortRangeStart: frontendPortRangeStart != -1 ? frontendPortRangeStart : null + frontendPortRangeEnd: frontendPortRangeEnd != -1 ? frontendPortRangeEnd : null + idleTimeoutInMinutes: idleTimeoutInMinutes + protocol: protocol + } + parent: loadBalancer +} + +@description('The name of the inbound NAT rule') +output name string = inboundNatRule.name + +@description('The resource ID of the inbound NAT rule') +output resourceId string = inboundNatRule.id + +@description('The resource group the inbound NAT rule was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/readme.md b/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/readme.md new file mode 100644 index 000000000..00e271ae0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/readme.md @@ -0,0 +1,52 @@ +# Load Balancer Inbound NAT Rules `[Microsoft.Network/loadBalancers/inboundNatRules]` + +This module deploys load balancers inbound NAT rules. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/loadBalancers/inboundNatRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `frontendIPConfigurationName` | string | The name of the frontend IP address to set for the inbound NAT rule | +| `frontendPort` | int | The port for the external endpoint. Port numbers for each rule must be unique within the Load Balancer. | +| `loadBalancerName` | string | The name of the parent load balancer | +| `name` | string | The name of the inbound NAT rule | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backendAddressPoolName` | string | `''` | | Name of the backend address pool | +| `backendPort` | int | `[parameters('frontendPort')]` | | The port used for the internal endpoint. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableFloatingIP` | bool | `False` | | Configures a virtual machine's endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. This setting can't be changed after you create the endpoint. | +| `enableTcpReset` | bool | `False` | | Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. This element is only used when the protocol is set to TCP. | +| `frontendPortRangeEnd` | int | `-1` | | The port range end for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeStart. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool. | +| `frontendPortRangeStart` | int | `-1` | | The port range start for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeEnd. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool. | +| `idleTimeoutInMinutes` | int | `4` | | The timeout for the TCP idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP. | +| `protocol` | string | `'Tcp'` | `[All, Tcp, Udp]` | The transport protocol for the endpoint. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the inbound NAT rule | +| `resourceGroupName` | string | The resource group the inbound NAT rule was deployed into | +| `resourceId` | string | The resource ID of the inbound NAT rule | + +## Template references + +- [Loadbalancers/Inboundnatrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/inboundNatRules) diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/version.json b/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/inboundNatRules/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/carml/1.0.1/Microsoft.Network/loadBalancers/readme.md b/carml/1.0.1/Microsoft.Network/loadBalancers/readme.md new file mode 100644 index 000000000..2da63f315 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/readme.md @@ -0,0 +1,243 @@ +# Load Balancers `[Microsoft.Network/loadBalancers]` + +This module deploys a load balancer. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/loadBalancers` | 2021-05-01 | +| `Microsoft.Network/loadBalancers/backendAddressPools` | 2021-05-01 | +| `Microsoft.Network/loadBalancers/inboundNatRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `frontendIPConfigurations` | array | Array of objects containing all frontend IP configurations | +| `name` | string | The Proximity Placement Groups Name | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backendAddressPools` | _[backendAddressPools](backendAddressPools/readme.md)_ array | `[]` | | Collection of backend address pools used by a load balancer. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `inboundNatRules` | _[inboundNatRules](inboundNatRules/readme.md)_ array | `[]` | | Collection of inbound NAT Rules used by a load balancer. Defining inbound NAT rules on your load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. They have to reference individual inbound NAT rules. | +| `loadBalancerSku` | string | `'Standard'` | `[Basic, Standard]` | Name of a load balancer SKU. | +| `loadBalancingRules` | array | `[]` | | Array of objects containing all load balancing rules | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `outboundRules` | array | `[]` | | The outbound rules. | +| `probes` | array | `[]` | | Array of objects containing all probes, these are references in the load balancing rules | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `frontendIPConfigurations` + +```json +"frontendIPConfigurations": { + "value": [ + { + "name": "p_hub-bfw-server-feip", + "properties": { + "publicIPAddressId": "[reference(variables('deploymentPIP-VPN')).outputs.publicIPAddressResourceId.value]", + "subnetId": "", + "privateIPAddress": "" + } + } + ] +} +``` + +### Parameter Usage: `backendAddressPools` + +```json +"backendAddressPools": { + "value": [ + { + "name": "p_hub-bfw-server-bepool", + "properties": { + "loadBalancerBackendAddresses": [ + { + "name": "iacs-sh-main-pd-01-euw-rg-network_awefwa01p-nic-int-01ipconfig-internal", + "properties": { + "virtualNetwork": { + "id": "[reference(variables('deploymentVNET')).outputs.vNetResourceId.value]" + }, + "ipAddress": "172.22.232.5" + } + }, + { + "name": "iacs-sh-main-pd-01-euw-rg-network_awefwa01p-ha-nic-int-01ipconfig-internal", + "properties": { + "virtualNetwork": { + "id": "[reference(variables('deploymentVNET')).outputs.vNetResourceId.value]" + }, + "ipAddress": "172.22.232.6" + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `loadBalancingRules` + +```json +"loadBalancingRules": { +"value": [ + { + "name": "p_hub-bfw-server-IPSEC-IKE-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 500, + "backendPort": 500, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-IPSEC-NATT-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 4500, + "backendPort": 4500, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-TINA-UDP-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 691, + "backendPort": 691, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-TINA-TCP-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Tcp", + "frontendPort": 691, + "backendPort": 691, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + } +] +} +``` + +### Parameter Usage: `probes` + +```json +"probes": { + "value": [ + { + "name": "p_hub-bfw-server-tcp-65001-probe", + "properties": { + "protocol": "Tcp", + "port": 65001, + "intervalInSeconds": 5, + "numberOfProbes": 2 + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `backendpools` | array | The backend address pools available in the load balancer. | +| `name` | string | The name of the load balancer | +| `resourceGroupName` | string | The resource group the load balancer was deployed into | +| `resourceId` | string | The resource ID of the load balancer | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Loadbalancers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers) +- [Loadbalancers/Backendaddresspools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/backendAddressPools) +- [Loadbalancers/Inboundnatrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/inboundNatRules) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/loadBalancers/version.json b/carml/1.0.1/Microsoft.Network/loadBalancers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/loadBalancers/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/carml/1.0.1/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..621a3ee40 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(localNetworkGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: localNetworkGateway +}] diff --git a/carml/1.0.1/Microsoft.Network/localNetworkGateways/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/localNetworkGateways/.parameters/parameters.json new file mode 100644 index 000000000..878777fb1 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/localNetworkGateways/.parameters/parameters.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lng-x-001" + }, + "localAddressPrefixes": { + "value": [ + "192.168.1.0/24" + ] + }, + "localGatewayPublicIpAddress": { + "value": "8.8.8.8" + }, + "localAsn": { + "value": "65123" + }, + "localBgpPeeringAddress": { + "value": "192.168.1.5" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/localNetworkGateways/deploy.bicep b/carml/1.0.1/Microsoft.Network/localNetworkGateways/deploy.bicep new file mode 100644 index 000000000..a8570e13a --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/localNetworkGateways/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. Name of the Local Network Gateway') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. List of the local (on-premises) IP address ranges') +param localAddressPrefixes array + +@description('Required. Public IP of the local gateway') +param localGatewayPublicIpAddress string + +@description('Optional. The BGP speaker\'s ASN. Not providing this value will automatically disable BGP on this Local Network Gateway resource.') +param localAsn string = '' + +@description('Optional. The BGP peering address and BGP identifier of this BGP speaker. Not providing this value will automatically disable BGP on this Local Network Gateway resource.') +param localBgpPeeringAddress string = '' + +@description('Optional. The weight added to routes learned from this BGP speaker. This will only take effect if both the localAsn and the localBgpPeeringAddress values are provided.') +param localPeerWeight string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. FQDN of local network gateway.') +param fqdn string = '' + +var bgpSettings = { + asn: localAsn + bgpPeeringAddress: localBgpPeeringAddress + peerWeight: !empty(localPeerWeight) ? localPeerWeight : '0' +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-08-01' = { + name: name + location: location + tags: tags + properties: { + localNetworkAddressSpace: { + addressPrefixes: localAddressPrefixes + } + fqdn: !empty(fqdn) ? fqdn : null + gatewayIpAddress: localGatewayPublicIpAddress + bgpSettings: !empty(localAsn) && !empty(localBgpPeeringAddress) ? bgpSettings : null + } +} + +resource localNetworkGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${localNetworkGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: localNetworkGateway +} + +module localNetworkGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LocalNetworkGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: localNetworkGateway.id + } +}] + +@description('The resource ID of the local network gateway') +output resourceId string = localNetworkGateway.id + +@description('The resource group the local network gateway was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the local network gateway') +output name string = localNetworkGateway.name diff --git a/carml/1.0.1/Microsoft.Network/localNetworkGateways/readme.md b/carml/1.0.1/Microsoft.Network/localNetworkGateways/readme.md new file mode 100644 index 000000000..1b9ab9d57 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/localNetworkGateways/readme.md @@ -0,0 +1,98 @@ +# Local Network Gateways `[Microsoft.Network/localNetworkGateways]` + +This module deploys a local network gateway. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/localNetworkGateways` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `localAddressPrefixes` | array | List of the local (on-premises) IP address ranges | +| `localGatewayPublicIpAddress` | string | Public IP of the local gateway | +| `name` | string | Name of the Local Network Gateway | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `fqdn` | string | `''` | | FQDN of local network gateway. | +| `localAsn` | string | `''` | | The BGP speaker's ASN. Not providing this value will automatically disable BGP on this Local Network Gateway resource. | +| `localBgpPeeringAddress` | string | `''` | | The BGP peering address and BGP identifier of this BGP speaker. Not providing this value will automatically disable BGP on this Local Network Gateway resource. | +| `localPeerWeight` | string | `''` | | The weight added to routes learned from this BGP speaker. This will only take effect if both the localAsn and the localBgpPeeringAddress values are provided. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the local network gateway | +| `resourceGroupName` | string | The resource group the local network gateway was deployed into | +| `resourceId` | string | The resource ID of the local network gateway | + +## Template references + +- [Localnetworkgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/localNetworkGateways) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/localNetworkGateways/version.json b/carml/1.0.1/Microsoft.Network/localNetworkGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/localNetworkGateways/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/carml/1.0.1/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5c200476b --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(natGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: natGateway +}] diff --git a/carml/1.0.1/Microsoft.Network/natGateways/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/natGateways/.parameters/parameters.json new file mode 100644 index 000000000..6f5ac729c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/natGateways/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ngw-x-001" + }, + "natGatewayPublicIpAddress": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/natGateways/deploy.bicep b/carml/1.0.1/Microsoft.Network/natGateways/deploy.bicep new file mode 100644 index 000000000..e13ac102e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/natGateways/deploy.bicep @@ -0,0 +1,214 @@ +@description('Required. Name of the Azure Bastion resource') +param name string + +@description('Optional. The idle timeout of the nat gateway.') +param idleTimeoutInMinutes int = 5 + +@description('Optional. Use to have a new Public IP Address created for the NAT Gateway.') +param natGatewayPublicIpAddress bool = false + +@description('Optional. Specifies the name of the Public IP used by the NAT Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the Bastion\'s name.') +param natGatewayPipName string = '' + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param natGatewayPublicIPPrefixId string = '' + +@description('Optional. DNS name of the Public IP resource. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com') +param natGatewayDomainNameLabel string = '' + +@description('Optional. Existing Public IP Address resource names to use for the NAT Gateway.') +param publicIpAddresses array = [] + +@description('Optional. Existing Public IP Prefixes resource names to use for the NAT Gateway.') +param publicIpPrefixes array = [] + +@description('Optional. A list of availability zones denoting the zone in which Nat Gateway should be deployed.') +param zones array = [] + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var natGatewayPipName_var = (empty(natGatewayPipName) ? '${name}-pip' : natGatewayPipName) +var natGatewayPublicIPPrefix = { + id: natGatewayPublicIPPrefixId +} + +var natGatewayPropertyPublicIPPrefixes = [for publicIpPrefix in publicIpPrefixes: { + id: az.resourceId('Microsoft.Network/publicIPPrefixes', publicIpPrefix) +}] +var natGatewayPropertyPublicIPAddresses = [for publicIpAddress in publicIpAddresses: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', publicIpAddress) +}] +var natGatewayProperties = { + idleTimeoutInMinutes: idleTimeoutInMinutes + publicIpPrefixes: natGatewayPropertyPublicIPPrefixes + publicIpAddresses: natGatewayPropertyPublicIPAddresses +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +// PUBLIC IP +// ========= +resource publicIP 'Microsoft.Network/publicIPAddresses@2021-05-01' = if (natGatewayPublicIpAddress) { + name: natGatewayPipName_var + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: { + publicIPAllocationMethod: 'Static' + publicIPPrefix: !empty(natGatewayPublicIPPrefixId) ? natGatewayPublicIPPrefix : null + dnsSettings: !empty(natGatewayDomainNameLabel) ? json('{"domainNameLabel": "${natGatewayDomainNameLabel}"}') : null + } +} + +resource publicIP_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIP.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIP +} + +resource publicIP_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIP +} + +// NAT GATEWAY +// =========== +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: natGatewayProperties + zones: zones +} + +resource natGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${natGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: natGateway +} + +module natGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NatGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: natGateway.id + } +}] + +@description('The name of the NAT Gateway') +output name string = natGateway.name + +@description('The resource ID of the NAT Gateway') +output resourceId string = natGateway.id + +@description('The resource group the NAT Gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/natGateways/readme.md b/carml/1.0.1/Microsoft.Network/natGateways/readme.md new file mode 100644 index 000000000..309734fea --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/natGateways/readme.md @@ -0,0 +1,112 @@ +# NAT Gateways `[Microsoft.Network/natGateways]` + +This module deploys a NAT gateway. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/natGateways` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Bastion resource | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `idleTimeoutInMinutes` | int | `5` | | The idle timeout of the nat gateway. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `natGatewayDomainNameLabel` | string | `''` | | DNS name of the Public IP resource. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com | +| `natGatewayPipName` | string | `''` | | Specifies the name of the Public IP used by the NAT Gateway. If it's not provided, a '-pip' suffix will be appended to the Bastion's name. | +| `natGatewayPublicIpAddress` | bool | `False` | | Use to have a new Public IP Address created for the NAT Gateway. | +| `natGatewayPublicIPPrefixId` | string | `''` | | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `publicIpAddresses` | array | `[]` | | Existing Public IP Address resource names to use for the NAT Gateway. | +| `publicIpPrefixes` | array | `[]` | | Existing Public IP Prefixes resource names to use for the NAT Gateway. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags for the resource. | +| `zones` | array | `[]` | | A list of availability zones denoting the zone in which Nat Gateway should be deployed. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT Gateway | +| `resourceGroupName` | string | The resource group the NAT Gateway was deployed into | +| `resourceId` | string | The resource ID of the NAT Gateway | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Natgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/natGateways) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/natGateways/version.json b/carml/1.0.1/Microsoft.Network/natGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/natGateways/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/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..3e691d4ae --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,58 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkSecurityGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: networkSecurityGroup +}] diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.parameters/min.parameters.json new file mode 100644 index 000000000..b07946467 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-nsg-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json new file mode 100644 index 000000000..c8f75d3aa --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json @@ -0,0 +1,100 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-nsg-x-001" + }, + "securityRules": { + "value": [ + { + "name": "Specific", + "properties": { + "description": "Tests specific IPs and ports", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8080", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + { + "name": "Ranges", + "properties": { + "description": "Tests Ranges", + "protocol": "*", + "access": "Allow", + "priority": 101, + "direction": "Inbound", + "sourcePortRanges": [ + "80", + "81" + ], + "destinationPortRanges": [ + "90", + "91" + ], + "sourceAddressPrefixes": [ + "10.0.0.0/16", + "10.1.0.0/16" + ], + "destinationAddressPrefixes": [ + "10.2.0.0/16", + "10.3.0.0/16" + ] + } + }, + { + "name": "Port_8082", + "properties": { + "description": "Allow inbound access on TCP 8082", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8082", + "access": "Allow", + "priority": 102, + "direction": "Inbound", + "sourceApplicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ], + "destinationApplicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ] + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/deploy.bicep b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/deploy.bicep new file mode 100644 index 000000000..61d49565c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/deploy.bicep @@ -0,0 +1,168 @@ +@description('Required. Name of the Network Security Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed.') +param securityRules array = [] + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the NSG resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +]) +param diagnosticLogCategoriesToEnable array = [ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + securityRules: [for securityRule in securityRules: { + name: securityRule.name + properties: { + protocol: securityRule.properties.protocol + access: securityRule.properties.access + priority: securityRule.properties.priority + direction: securityRule.properties.direction + description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' + sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : '' + sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : [] + destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : '' + destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : [] + sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : '' + destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : '' + sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : [] + destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : [] + sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : [] + destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : [] + } + }] + } +} + +module networkSecurityGroup_securityRules 'securityRules/deploy.bicep' = [for (securityRule, index) in securityRules: { + name: '${uniqueString(deployment().name, location)}-securityRule-${index}' + params: { + name: securityRule.name + networkSecurityGroupName: networkSecurityGroup.name + protocol: securityRule.properties.protocol + access: securityRule.properties.access + priority: securityRule.properties.priority + direction: securityRule.properties.direction + description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' + sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : '' + sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : [] + destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : '' + destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : [] + sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : '' + destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : '' + sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : [] + destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : [] + sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : [] + destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : [] + } +}] + +resource networkSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkSecurityGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkSecurityGroup +} + +resource networkSecurityGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: networkSecurityGroup +} + +module networkSecurityGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NSG-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkSecurityGroup.id + } +}] + +@description('The resource group the network security group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the network security group') +output resourceId string = networkSecurityGroup.id + +@description('The name of the network security group') +output name string = networkSecurityGroup.name diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/readme.md b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/readme.md new file mode 100644 index 000000000..4272efbf6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/readme.md @@ -0,0 +1,104 @@ +# Network Security Groups `[Microsoft.Network/networkSecurityGroups]` + +This template deploys a network security group (NSG) with optional security rules. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/networkSecurityGroups` | 2021-05-01 | +| `Microsoft.Network/networkSecurityGroups/securityRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Network Security Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityRules` | _[securityRules](securityRules/readme.md)_ array | `[]` | | Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed. | +| `tags` | object | `{object}` | | Tags of the NSG resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the network security group | +| `resourceGroupName` | string | The resource group the network security group was deployed into | +| `resourceId` | string | The resource ID of the network security group | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networksecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups) +- [Networksecuritygroups/Securityrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups/securityRules) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/deploy.bicep b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/deploy.bicep new file mode 100644 index 000000000..62f7a6e7d --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/deploy.bicep @@ -0,0 +1,117 @@ +@sys.description('Required. The name of the security rule') +param name string + +@sys.description('Required. The name of the network security group to deploy the security rule into') +param networkSecurityGroupName string + +@sys.description('Optional. Whether network traffic is allowed or denied.') +@allowed([ + 'Allow' + 'Deny' +]) +param access string = 'Deny' + +@sys.description('Optional. A description for this rule') +@maxLength(140) +param description string = '' + +@sys.description('Optional. The destination address prefix. CIDR or destination IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used.') +param destinationAddressPrefix string = '' + +@sys.description('Optional. The destination address prefixes. CIDR or destination IP ranges.') +param destinationAddressPrefixes array = [] + +@sys.description('Optional. The application security group specified as destination.') +param destinationApplicationSecurityGroups array = [] + +@sys.description('Optional. The destination port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports.') +param destinationPortRange string = '' + +@sys.description('Optional. The destination port ranges.') +param destinationPortRanges array = [] + +@sys.description('Required. The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic.') +@allowed([ + 'Inbound' + 'Outbound' +]) +param direction string + +@sys.description('Required. The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule.') +param priority int + +@sys.description('Required. Network protocol this rule applies to.') +@allowed([ + '*' + 'Ah' + 'Esp' + 'Icmp' + 'Tcp' + 'Udp' +]) +param protocol string + +@sys.description('Optional. The CIDR or source IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. If this is an ingress rule, specifies where network traffic originates from.') +param sourceAddressPrefix string = '' + +@sys.description('Optional. The CIDR or source IP ranges.') +param sourceAddressPrefixes array = [] + +@sys.description('Optional. The application security group specified as source.') +param sourceApplicationSecurityGroups array = [] + +@sys.description('Optional. The source port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports.') +param sourcePortRange string = '' + +@sys.description('Optional. The source port ranges.') +param sourcePortRanges array = [] + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = { + name: networkSecurityGroupName +} + +resource securityRule 'Microsoft.Network/networkSecurityGroups/securityRules@2021-05-01' = { + name: name + parent: networkSecurityGroup + properties: { + access: access + description: description + destinationAddressPrefix: destinationAddressPrefix + destinationAddressPrefixes: destinationAddressPrefixes + destinationApplicationSecurityGroups: destinationApplicationSecurityGroups + destinationPortRange: destinationPortRange + destinationPortRanges: destinationPortRanges + direction: direction + priority: priority + protocol: protocol + sourceAddressPrefix: sourceAddressPrefix + sourceAddressPrefixes: sourceAddressPrefixes + sourceApplicationSecurityGroups: sourceApplicationSecurityGroups + sourcePortRange: sourcePortRange + sourcePortRanges: sourcePortRanges + } +} + +@sys.description('The resource group the security rule was deployed into') +output resourceGroupName string = resourceGroup().name + +@sys.description('The resource ID of the security rule') +output resourceId string = securityRule.id + +@sys.description('The name of the security rule') +output name string = securityRule.name diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/readme.md b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/readme.md new file mode 100644 index 000000000..2cbeb3eea --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/readme.md @@ -0,0 +1,57 @@ +# Network Security Groups Security Rules `[Microsoft.Network/networkSecurityGroups/securityRules]` + +This module deploys Network Security Group Security Rules. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkSecurityGroups/securityRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `direction` | string | `[Inbound, Outbound]` | The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic. | +| `name` | string | | The name of the security rule | +| `networkSecurityGroupName` | string | | The name of the network security group to deploy the security rule into | +| `priority` | int | | The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule. | +| `protocol` | string | `[*, Ah, Esp, Icmp, Tcp, Udp]` | Network protocol this rule applies to. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `access` | string | `'Deny'` | `[Allow, Deny]` | Whether network traffic is allowed or denied. | +| `description` | string | `''` | | A description for this rule | +| `destinationAddressPrefix` | string | `''` | | The destination address prefix. CIDR or destination IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. | +| `destinationAddressPrefixes` | array | `[]` | | The destination address prefixes. CIDR or destination IP ranges. | +| `destinationApplicationSecurityGroups` | array | `[]` | | The application security group specified as destination. | +| `destinationPortRange` | string | `''` | | The destination port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports. | +| `destinationPortRanges` | array | `[]` | | The destination port ranges. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `sourceAddressPrefix` | string | `''` | | The CIDR or source IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. If this is an ingress rule, specifies where network traffic originates from. | +| `sourceAddressPrefixes` | array | `[]` | | The CIDR or source IP ranges. | +| `sourceApplicationSecurityGroups` | array | `[]` | | The application security group specified as source. | +| `sourcePortRange` | string | `''` | | The source port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports. | +| `sourcePortRanges` | array | `[]` | | The source port ranges. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the security rule | +| `resourceGroupName` | string | The resource group the security rule was deployed into | +| `resourceId` | string | The resource ID of the security rule | + +## Template references + +- [Networksecuritygroups/Securityrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups/securityRules) diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/version.json b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/securityRules/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Network/networkSecurityGroups/version.json b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkSecurityGroups/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/carml/1.0.1/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..8d685ea44 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkWatcher.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: networkWatcher +}] diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/networkWatchers/.parameters/min.parameters.json new file mode 100644 index 000000000..78acbb0c7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "value": "northeurope" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/networkWatchers/.parameters/parameters.json new file mode 100644 index 000000000..78a7e1f27 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/.parameters/parameters.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "adp-<>-az-nw-x-001" + }, + "flowLogs": { + "value": [ + { + "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "enabled": false + }, + { + "name": "adp-<>-az-nsg-x-apgw-flowlog", + "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-apgw", + "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "formatVersion": 1, + "trafficAnalyticsInterval": 10, + "retentionInDays": 8 + } + ] + }, + "connectionMonitors": { + "value": [ + { + "name": "adp-<>-az-conn-mon-x-001", + "endpoints": [ + { + "name": "<>-az-subnet-x-001(validation-rg)", + "type": "AzureVM", + "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/virtualMachines/adp-<>-vm-01" + }, + { + "name": "Office Portal", + "type": "ExternalAddress", + "address": "www.office.com" + } + ], + "testConfigurations": [ + { + "name": "HTTP Test", + "testFrequencySec": 30, + "protocol": "Http", + "httpConfiguration": { + "port": 80, + "method": "Get", + "requestHeaders": [], + "validStatusCodeRanges": [ + "200" + ], + "preferHTTPS": false + }, + "successThreshold": { + "checksFailedPercent": 5, + "roundTripTimeMs": 100 + } + } + ], + "testGroups": [ + { + "name": "TestHTTPBing", + "disable": false, + "testConfigurations": [ + "HTTP Test" + ], + "sources": [ + "<>-az-subnet-x-001(validation-rg)" + ], + "destinations": [ + "Office Portal" + ] + } + ], + "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep b/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep new file mode 100644 index 000000000..492ee37c4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep @@ -0,0 +1,73 @@ +@description('Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG') +param networkWatcherName string = 'NetworkWatcher_${resourceGroup().location}' + +@description('Optional. Name of the resource.') +param name string + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. List of connection monitor endpoints.') +param endpoints array = [] + +@description('Optional. List of connection monitor test configurations.') +param testConfigurations array = [] + +@description('Optional. List of connection monitor test groups.') +param testGroups array = [] + +@description('Optional. Specify the Log Analytics Workspace Resource ID') +param workspaceResourceId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var outputs = !empty(workspaceResourceId) ? [ + { + type: 'Workspace' + workspaceSettings: { + workspaceResourceId: workspaceResourceId + } + } +] : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: networkWatcherName +} + +resource connectionMonitor 'Microsoft.Network/networkWatchers/connectionMonitors@2021-05-01' = { + name: name + parent: networkWatcher + tags: tags + location: location + properties: { + endpoints: endpoints + testConfigurations: testConfigurations + testGroups: testGroups + outputs: outputs + } +} + +@description('The name of the deployed connection monitor') +output name string = connectionMonitor.name + +@description('The resource ID of the deployed connection monitor') +output resourceId string = connectionMonitor.id + +@description('The resource group the connection monitor was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/readme.md b/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/readme.md new file mode 100644 index 000000000..b1d287ba0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/readme.md @@ -0,0 +1,61 @@ +# Network Watchers Connection Monitors `[Microsoft.Network/networkWatchers/connectionMonitors]` + +This template deploys Connection Monitors. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkWatchers/connectionMonitors` | 2021-05-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endpoints` | array | `[]` | List of connection monitor endpoints. | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `name` | string | | Name of the resource. | +| `networkWatcherName` | string | `[format('NetworkWatcher_{0}', resourceGroup().location)]` | Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG | +| `tags` | object | `{object}` | Tags of the resource. | +| `testConfigurations` | array | `[]` | List of connection monitor test configurations. | +| `testGroups` | array | `[]` | List of connection monitor test groups. | +| `workspaceResourceId` | string | `''` | Specify the Log Analytics Workspace Resource ID | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed connection monitor | +| `resourceGroupName` | string | The resource group the connection monitor was deployed into | +| `resourceId` | string | The resource ID of the deployed connection monitor | + +## Template references + +- [Networkwatchers/Connectionmonitors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/connectionMonitors) diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/version.json b/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/connectionMonitors/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/carml/1.0.1/Microsoft.Network/networkWatchers/deploy.bicep b/carml/1.0.1/Microsoft.Network/networkWatchers/deploy.bicep new file mode 100644 index 000000000..6f4539ad0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/deploy.bicep @@ -0,0 +1,105 @@ +@description('Required. Name of the Network Watcher resource (hidden)') +@minLength(1) +param name string = 'NetworkWatcher_${location}' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array that contains the Connection Monitors') +param connectionMonitors array = [] + +@description('Optional. Array that contains the Flow Logs') +param flowLogs array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource networkWatcher_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkWatcher.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkWatcher +} + +module networkWatcher_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NW-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkWatcher.id + } +}] + +module networkWatcher_connectionMonitors 'connectionMonitors/deploy.bicep' = [for (connectionMonitor, index) in connectionMonitors: { + name: '${uniqueString(deployment().name, location)}-NW-ConnectionMonitor-${index}' + params: { + endpoints: contains(connectionMonitor, 'endpoints') ? connectionMonitor.endpoints : [] + name: connectionMonitor.name + networkWatcherName: networkWatcher.name + testConfigurations: contains(connectionMonitor, 'testConfigurations') ? connectionMonitor.testConfigurations : [] + testGroups: contains(connectionMonitor, 'testGroups') ? connectionMonitor.testGroups : [] + workspaceResourceId: contains(connectionMonitor, 'workspaceResourceId') ? connectionMonitor.workspaceResourceId : '' + } +}] + +module networkWatcher_flowLogs 'flowLogs/deploy.bicep' = [for (flowLog, index) in flowLogs: { + name: '${uniqueString(deployment().name, location)}-NW-FlowLog-${index}' + params: { + enabled: contains(flowLog, 'enabled') ? flowLog.enabled : true + formatVersion: contains(flowLog, 'formatVersion') ? flowLog.formatVersion : 2 + location: contains(flowLog, 'location') ? flowLog.location : location + name: contains(flowLog, 'name') ? flowLog.name : '${last(split(flowLog.targetResourceId, '/'))}-${split(flowLog.targetResourceId, '/')[4]}-flowlog' + networkWatcherName: networkWatcher.name + retentionInDays: contains(flowLog, 'retentionInDays') ? flowLog.retentionInDays : 365 + storageId: flowLog.storageId + targetResourceId: flowLog.targetResourceId + trafficAnalyticsInterval: contains(flowLog, 'trafficAnalyticsInterval') ? flowLog.trafficAnalyticsInterval : 60 + workspaceResourceId: contains(flowLog, 'workspaceResourceId') ? flowLog.workspaceResourceId : '' + } +}] + +@description('The name of the deployed network watcher') +output name string = networkWatcher.name + +@description('The resource ID of the deployed network watcher') +output resourceId string = networkWatcher.id + +@description('The resource group the network watcher was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep b/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep new file mode 100644 index 000000000..f148fef06 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep @@ -0,0 +1,102 @@ +@description('Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG') +param networkWatcherName string = 'NetworkWatcher_${resourceGroup().location}' + +@description('Optional. Name of the resource.') +param name string = '${last(split(targetResourceId, '/'))}-${split(targetResourceId, '/')[4]}-flowlog' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Resource ID of the NSG that must be enabled for Flow Logs.') +param targetResourceId string + +@description('Required. Resource ID of the diagnostic storage account.') +param storageId string + +@description('Optional. If the flow log should be enabled') +param enabled bool = true + +@description('Optional. The flow log format version') +@allowed([ + 1 + 2 +]) +param formatVersion int = 2 + +@description('Optional. Specify the Log Analytics Workspace Resource ID') +param workspaceResourceId string = '' + +@description('Optional. The interval in minutes which would decide how frequently TA service should do flow analytics.') +@allowed([ + 10 + 60 +]) +param trafficAnalyticsInterval int = 60 + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param retentionInDays int = 365 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var flowAnalyticsConfiguration = !empty(workspaceResourceId) && enabled == true ? { + networkWatcherFlowAnalyticsConfiguration: { + enabled: true + workspaceResourceId: workspaceResourceId + trafficAnalyticsInterval: trafficAnalyticsInterval + } +} : { + networkWatcherFlowAnalyticsConfiguration: { + enabled: false + } +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: networkWatcherName +} + +resource flowLog 'Microsoft.Network/networkWatchers/flowLogs@2021-05-01' = { + name: name + parent: networkWatcher + tags: tags + location: location + properties: { + targetResourceId: targetResourceId + storageId: storageId + enabled: enabled + retentionPolicy: { + days: retentionInDays + enabled: retentionInDays == 0 ? false : true + } + format: { + type: 'JSON' + version: formatVersion + } + flowAnalyticsConfiguration: flowAnalyticsConfiguration + } +} +@description('The name of the flow log') +output name string = flowLog.name + +@description('The resource ID of the flow log') +output resourceId string = flowLog.id + +@description('The resource group the flow log was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/readme.md b/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/readme.md new file mode 100644 index 000000000..e7f324bd8 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/readme.md @@ -0,0 +1,69 @@ +# NSG Flow Logs `[Microsoft.Network/networkWatchers/flowLogs]` + +This module controls the Network Security Group Flow Logs and analytics settings +**Note: this module must be run on the Resource Group where Network Watcher is deployed** + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkWatchers/flowLogs` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageId` | string | Resource ID of the diagnostic storage account. | +| `targetResourceId` | string | Resource ID of the NSG that must be enabled for Flow Logs. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enabled` | bool | `True` | | If the flow log should be enabled | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `formatVersion` | int | `2` | `[1, 2]` | The flow log format version | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `name` | string | `[format('{0}-{1}-flowlog', last(split(parameters('targetResourceId'), '/')), split(parameters('targetResourceId'), '/')[4])]` | | Name of the resource. | +| `networkWatcherName` | string | `[format('NetworkWatcher_{0}', resourceGroup().location)]` | | Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG | +| `retentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `trafficAnalyticsInterval` | int | `60` | `[10, 60]` | The interval in minutes which would decide how frequently TA service should do flow analytics. | +| `workspaceResourceId` | string | `''` | | Specify the Log Analytics Workspace Resource ID | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the flow log | +| `resourceGroupName` | string | The resource group the flow log was deployed into | +| `resourceId` | string | The resource ID of the flow log | + +## Template references + +- [Networkwatchers/Flowlogs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/flowLogs) diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/version.json b/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/flowLogs/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/carml/1.0.1/Microsoft.Network/networkWatchers/readme.md b/carml/1.0.1/Microsoft.Network/networkWatchers/readme.md new file mode 100644 index 000000000..8e5705d32 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/readme.md @@ -0,0 +1,98 @@ +# Network Watchers `[Microsoft.Network/networkWatchers]` + +This template deploys a network watcher. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/networkWatchers` | 2021-05-01 | +| `Microsoft.Network/networkWatchers/connectionMonitors` | 2021-05-01 | +| `Microsoft.Network/networkWatchers/flowLogs` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | `[format('NetworkWatcher_{0}', parameters('location'))]` | Name of the Network Watcher resource (hidden) | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `connectionMonitors` | _[connectionMonitors](connectionMonitors/readme.md)_ array | `[]` | | Array that contains the Connection Monitors | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `flowLogs` | _[flowLogs](flowLogs/readme.md)_ array | `[]` | | Array that contains the Flow Logs | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed network watcher | +| `resourceGroupName` | string | The resource group the network watcher was deployed into | +| `resourceId` | string | The resource ID of the deployed network watcher | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networkwatchers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers) +- [Networkwatchers/Connectionmonitors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/connectionMonitors) +- [Networkwatchers/Flowlogs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/flowLogs) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/networkWatchers/version.json b/carml/1.0.1/Microsoft.Network/networkWatchers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/networkWatchers/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/carml/1.0.1/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..45993398e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2018-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateDnsZone.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: privateDnsZone +}] diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/.parameters/min.parameters.json new file mode 100644 index 000000000..d33fbd032 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-privdns-x-001.com" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/.parameters/parameters.json new file mode 100644 index 000000000..0668e824c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/.parameters/parameters.json @@ -0,0 +1,139 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-privdns-x-002.com" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "AAAA": { + "value": [ + { + "name": "AAAA_2001_0db8_85a3_0000_0000_8a2e_0370_7334", + "ttl": 3600, + "aaaaRecords": [ + { + "ipv6Address": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + } + ] + } + ] + }, + "A": { + "value": [ + { + "name": "A_10.240.4.4", + "ttl": 3600, + "aRecords": [ + { + "ipv4Address": "10.240.4.4" + } + ] + } + ] + }, + "CNAME": { + "value": [ + { + "name": "CNAME_test", + "ttl": 3600, + "cnameRecord": { + "cname": "test" + } + } + ] + }, + "MX": { + "value": [ + { + "name": "MX_contoso", + "ttl": 3600, + "mxRecords": [ + { + "exchange": "contoso.com", + "preference": 100 + } + ] + } + ] + }, + "PTR": { + "value": [ + { + "name": "PTR_contoso", + "ttl": 3600, + "ptrRecords": [ + { + "ptrdname": "contoso.com" + } + ] + } + ] + }, + "SOA": { + "value": [ + { + "name": "@", + "ttl": 3600, + "soaRecord": { + "email": "azureprivatedns-host.microsoft.com", + "expireTime": 2419200, + "host": "azureprivatedns.net", + "minimumTtl": 10, + "refreshTime": 3600, + "retryTime": 300, + "serialNumber": "1" + } + } + ] + }, + "SRV": { + "value": [ + { + "name": "SRV_contoso", + "ttl": 3600, + "srvRecords": [ + { + "port": 9332, + "priority": 0, + "target": "test.contoso.com", + "weight": 0 + } + ] + } + ] + }, + "TXT": { + "value": [ + { + "name": "TXT_test", + "ttl": 3600, + "txtRecords": [ + { + "value": [ + "test" + ] + } + ] + } + ] + }, + "virtualNetworkLinks": { + "value": [ + { + "virtualNetworkResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001", + "registrationEnabled": true + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/A/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/A/deploy.bicep new file mode 100644 index 000000000..59ead85ae --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/A/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the A record.') +param name string + +@description('Optional. The list of A records in the record set.') +param aRecords array = [] + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource A 'Microsoft.Network/privateDnsZones/A@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + aRecords: aRecords + metadata: metadata + ttl: ttl + } +} + +@description('The name of the deployed A record') +output name string = A.name + +@description('The resource ID of the deployed A record') +output resourceId string = A.id + +@description('The resource group of the deployed A record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/A/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/A/readme.md new file mode 100644 index 000000000..212bca2ad --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/A/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone A record `[Microsoft.Network/privateDnsZones/A]` + +This module deploys a Private DNS Zone A record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/A` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the A record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `aRecords` | array | `[]` | The list of A records in the record set. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `aRecords` + +```json +"aRecords": { + "value": [ + { + "ipv4Address": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed A record | +| `resourceGroupName` | string | The resource group of the deployed A record | +| `resourceId` | string | The resource ID of the deployed A record | + +## Template references + +- [Privatednszones/A](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/A) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/A/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/A/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/A/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/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/deploy.bicep new file mode 100644 index 000000000..1dd9efb23 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the AAAA record.') +param name string + +@description('Optional. The list of AAAA records in the record set.') +param aaaaRecords array = [] + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource AAAA 'Microsoft.Network/privateDnsZones/AAAA@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + aaaaRecords: aaaaRecords + metadata: metadata + ttl: ttl + } +} + +@description('The name of the deployed AAAA record') +output name string = AAAA.name + +@description('The resource ID of the deployed AAAA record') +output resourceId string = AAAA.id + +@description('The resource group of the deployed AAAA record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/readme.md new file mode 100644 index 000000000..566e29d47 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone AAAA record `[Microsoft.Network/privateDnsZones/AAAA]` + +This module deploys a Private DNS Zone AAAA record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/AAAA` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AAAA record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `aaaaRecords` | array | `[]` | The list of AAAA records in the record set. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `aaaaRecords` + +```json +"aaaaRecords": { + "value": [ + { + "ipv6Address": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed AAAA record | +| `resourceGroupName` | string | The resource group of the deployed AAAA record | +| `resourceId` | string | The resource ID of the deployed AAAA record | + +## Template references + +- [Privatednszones/AAAA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/AAAA) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/AAAA/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/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/deploy.bicep new file mode 100644 index 000000000..680f8d9ab --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the CNAME record.') +param name string + +@description('Optional. A CNAME record.') +param cnameRecord object = {} + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource CNAME 'Microsoft.Network/privateDnsZones/CNAME@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + cnameRecord: cnameRecord + metadata: metadata + ttl: ttl + } +} + +@description('The name of the deployed CNAME record') +output name string = CNAME.name + +@description('The resource ID of the deployed CNAME record') +output resourceId string = CNAME.id + +@description('The resource group of the deployed CNAME record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/readme.md new file mode 100644 index 000000000..665961ea9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/readme.md @@ -0,0 +1,45 @@ +# Private DNS Zone CNAME record `[Microsoft.Network/privateDnsZones/CNAME]` + +This module deploys a Private DNS Zone CNAME record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/CNAME` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the CNAME record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `cnameRecord` | object | `{object}` | A CNAME record. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed CNAME record | +| `resourceGroupName` | string | The resource group of the deployed CNAME record | +| `resourceId` | string | The resource ID of the deployed CNAME record | + +## Template references + +- [Privatednszones/CNAME](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/CNAME) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/CNAME/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/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/deploy.bicep new file mode 100644 index 000000000..49357b388 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the MX record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The list of MX records in the record set.') +param mxRecords array = [] + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource MX 'Microsoft.Network/privateDnsZones/MX@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + mxRecords: mxRecords + ttl: ttl + } +} + +@description('The name of the deployed MX record') +output name string = MX.name + +@description('The resource ID of the deployed MX record') +output resourceId string = MX.id + +@description('The resource group of the deployed MX record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/readme.md new file mode 100644 index 000000000..76d901b92 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/readme.md @@ -0,0 +1,58 @@ +# Private DNS Zone MX record `[Microsoft.Network/privateDnsZones/MX]` + +This module deploys a Private DNS Zone MX record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/MX` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the MX record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `mxRecords` | array | `[]` | The list of MX records in the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `mxRecords` + +```json +"mxRecords": { + "value": [ + { + "exchange": "string", + "preference": "int" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed MX record | +| `resourceGroupName` | string | The resource group of the deployed MX record | +| `resourceId` | string | The resource ID of the deployed MX record | + +## Template references + +- [Privatednszones/MX](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/MX) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/MX/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/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/deploy.bicep new file mode 100644 index 000000000..e7b066524 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the PTR record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The list of PTR records in the record set.') +param ptrRecords array = [] + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource PTR 'Microsoft.Network/privateDnsZones/PTR@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + ptrRecords: ptrRecords + ttl: ttl + } +} + +@description('The name of the deployed PTR record') +output name string = PTR.name + +@description('The resource ID of the deployed PTR record') +output resourceId string = PTR.id + +@description('The resource group of the deployed PTR record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/readme.md new file mode 100644 index 000000000..f57d6db67 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone PTR record `[Microsoft.Network/privateDnsZones/PTR]` + +This module deploys a Private DNS Zone PTR record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/PTR` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the PTR record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ptrRecords` | array | `[]` | The list of PTR records in the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `ptrRecords` + +```json +"ptrRecords": { + "value": [ + { + "ptrdname": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed PTR record | +| `resourceGroupName` | string | The resource group of the deployed PTR record | +| `resourceId` | string | The resource ID of the deployed PTR record | + +## Template references + +- [Privatednszones/PTR](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/PTR) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/PTR/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/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/deploy.bicep new file mode 100644 index 000000000..45079fc46 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the SOA record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. A SOA record.') +param soaRecord object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource SOA 'Microsoft.Network/privateDnsZones/SOA@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + soaRecord: soaRecord + ttl: ttl + } +} + +@description('The name of the deployed SOA record') +output name string = SOA.name + +@description('The resource ID of the deployed SOA record') +output resourceId string = SOA.id + +@description('The resource group of the deployed SOA record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/readme.md new file mode 100644 index 000000000..14dfbc674 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/readme.md @@ -0,0 +1,61 @@ +# Private DNS Zone SOA record `[Microsoft.Network/privateDnsZones/SOA]` + +This module deploys a Private DNS Zone SOA record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/SOA` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SOA record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `soaRecord` | object | `{object}` | A SOA record. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `soaRecord` + +```json +"soaRecord": { + "value": { + "email": "string", + "expireTime": "int", + "host": "string", + "minimumTtl": "int", + "refreshTime": "int", + "retryTime": "int", + "serialNumber": "int" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed SOA record | +| `resourceGroupName` | string | The resource group of the deployed SOA record | +| `resourceId` | string | The resource ID of the deployed SOA record | + +## Template references + +- [Privatednszones/SOA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SOA) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/SOA/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/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/deploy.bicep new file mode 100644 index 000000000..ace6ab941 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the SRV record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The list of SRV records in the record set.') +param srvRecords array = [] + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource SRV 'Microsoft.Network/privateDnsZones/SRV@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + srvRecords: srvRecords + ttl: ttl + } +} + +@description('The name of the deployed SRV record') +output name string = SRV.name + +@description('The resource ID of the deployed SRV record') +output resourceId string = SRV.id + +@description('The resource group of the deployed SRV record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/readme.md new file mode 100644 index 000000000..d1dd271a0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/readme.md @@ -0,0 +1,60 @@ +# Private DNS Zone SRV record `[Microsoft.Network/privateDnsZones/SRV]` + +This module deploys a Private DNS Zone TXT record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/SRV` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SRV record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `srvRecords` | array | `[]` | The list of SRV records in the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `srvRecords` + +```json +"srvRecords": { + "value": [ + { + "port": "int", + "priority": "int", + "target": "string", + "weight": "int" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed SRV record | +| `resourceGroupName` | string | The resource group of the deployed SRV record | +| `resourceId` | string | The resource ID of the deployed SRV record | + +## Template references + +- [Privatednszones/SRV](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SRV) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/SRV/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/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/deploy.bicep new file mode 100644 index 000000000..23d7bf3da --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the TXT record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. The list of TXT records in the record set.') +param txtRecords array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource TXT 'Microsoft.Network/privateDnsZones/TXT@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + ttl: ttl + txtRecords: txtRecords + } +} + +@description('The name of the deployed TXT record') +output name string = TXT.name + +@description('The resource ID of the deployed TXT record') +output resourceId string = TXT.id + +@description('The resource group of the deployed TXT record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/readme.md new file mode 100644 index 000000000..71fab1d72 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone TXT record `[Microsoft.Network/privateDnsZones/TXT]` + +This module deploys a Private DNS Zone TXT record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/TXT` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the TXT record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | +| `txtRecords` | array | `[]` | The list of TXT records in the record set. | + + +### Parameter Usage: `txtRecords` + +```json +"txtRecords": { + "value": [ + { + "value": [ "string" ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed TXT record | +| `resourceGroupName` | string | The resource group of the deployed TXT record | +| `resourceId` | string | The resource ID of the deployed TXT record | + +## Template references + +- [Privatednszones/TXT](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/TXT) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/TXT/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/carml/1.0.1/Microsoft.Network/privateDnsZones/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/deploy.bicep new file mode 100644 index 000000000..e040a8eff --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/deploy.bicep @@ -0,0 +1,196 @@ +@description('Required. Private DNS zone name.') +param name string + +@description('Optional. Array of A records.') +param a array = [] + +@description('Optional. Array of AAAA records.') +param aaaa array = [] + +@description('Optional. Array of CNAME records.') +param cname array = [] + +@description('Optional. Array of MX records.') +param mx array = [] + +@description('Optional. Array of PTR records.') +param ptr array = [] + +@description('Optional. Array of SOA records.') +param soa array = [] + +@description('Optional. Array of SRV records.') +param srv array = [] + +@description('Optional. Array of TXT records.') +param txt array = [] + +@description('Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties \'vnetResourceId\' and \'registrationEnabled\'. The \'vnetResourceId\' is a resource ID of a vNet to link, \'registrationEnabled\' (bool) enables automatic DNS registration in the zone for the linked vNet.') +param virtualNetworkLinks array = [] + +@description('Optional. The location of the PrivateDNSZone. Should be global.') +param location string = 'global' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: name + location: location + tags: tags +} + +module privateDnsZone_A 'A/deploy.bicep' = [for (aRecord, index) in a: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-ARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: aRecord.name + aRecords: contains(aRecord, 'aRecords') ? aRecord.aRecords : [] + metadata: contains(aRecord, 'metadata') ? aRecord.metadata : {} + ttl: contains(aRecord, 'ttl') ? aRecord.ttl : 3600 + } +}] + +module privateDnsZone_AAAA 'AAAA/deploy.bicep' = [for (aaaaRecord, index) in aaaa: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-AAAARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: aaaaRecord.name + aaaaRecords: contains(aaaaRecord, 'aaaaRecords') ? aaaaRecord.aaaaRecords : [] + metadata: contains(aaaaRecord, 'metadata') ? aaaaRecord.metadata : {} + ttl: contains(aaaaRecord, 'ttl') ? aaaaRecord.ttl : 3600 + } +}] + +module privateDnsZone_CNAME 'CNAME/deploy.bicep' = [for (cnameRecord, index) in cname: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-CNAMERecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: cnameRecord.name + cnameRecord: contains(cnameRecord, 'cnameRecord') ? cnameRecord.cnameRecord : {} + metadata: contains(cnameRecord, 'metadata') ? cnameRecord.metadata : {} + ttl: contains(cnameRecord, 'ttl') ? cnameRecord.ttl : 3600 + } +}] + +module privateDnsZone_MX 'MX/deploy.bicep' = [for (mxRecord, index) in mx: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-MXRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: mxRecord.name + metadata: contains(mxRecord, 'metadata') ? mxRecord.metadata : {} + mxRecords: contains(mxRecord, 'mxRecords') ? mxRecord.mxRecords : [] + ttl: contains(mxRecord, 'ttl') ? mxRecord.ttl : 3600 + } +}] + +module privateDnsZone_PTR 'PTR/deploy.bicep' = [for (ptrRecord, index) in ptr: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-PTRRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: ptrRecord.name + metadata: contains(ptrRecord, 'metadata') ? ptrRecord.metadata : {} + ptrRecords: contains(ptrRecord, 'ptrRecords') ? ptrRecord.ptrRecords : [] + ttl: contains(ptrRecord, 'ttl') ? ptrRecord.ttl : 3600 + } +}] + +module privateDnsZone_SOA 'SOA/deploy.bicep' = [for (soaRecord, index) in soa: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SOARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: soaRecord.name + metadata: contains(soaRecord, 'metadata') ? soaRecord.metadata : {} + soaRecord: contains(soaRecord, 'soaRecord') ? soaRecord.soaRecord : {} + ttl: contains(soaRecord, 'ttl') ? soaRecord.ttl : 3600 + } +}] + +module privateDnsZone_SRV 'SRV/deploy.bicep' = [for (srvRecord, index) in srv: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SRVRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: srvRecord.name + metadata: contains(srvRecord, 'metadata') ? srvRecord.metadata : {} + srvRecords: contains(srvRecord, 'srvRecords') ? srvRecord.srvRecords : [] + ttl: contains(srvRecord, 'ttl') ? srvRecord.ttl : 3600 + } +}] + +module privateDnsZone_TXT 'TXT/deploy.bicep' = [for (txtRecord, index) in txt: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-TXTRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: txtRecord.name + metadata: contains(txtRecord, 'metadata') ? txtRecord.metadata : {} + txtRecords: contains(txtRecord, 'txtRecords') ? txtRecord.txtRecords : [] + ttl: contains(txtRecord, 'ttl') ? txtRecord.ttl : 3600 + } +}] + +module privateDnsZone_virtualNetworkLinks 'virtualNetworkLinks/deploy.bicep' = [for (virtualNetworkLink, index) in virtualNetworkLinks: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-VirtualNetworkLink-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: contains(virtualNetworkLink, 'name') ? virtualNetworkLink.name : '${last(split(virtualNetworkLink.virtualNetworkResourceId, '/'))}-vnetlink' + virtualNetworkResourceId: virtualNetworkLink.virtualNetworkResourceId + location: contains(virtualNetworkLink, 'location') ? virtualNetworkLink.location : 'global' + registrationEnabled: contains(virtualNetworkLink, 'registrationEnabled') ? virtualNetworkLink.registrationEnabled : false + tags: contains(virtualNetworkLink, 'tags') ? virtualNetworkLink.tags : {} + } +}] + +resource privateDnsZone_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateDnsZone.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateDnsZone +} + +module privateDnsZone_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateDnsZone.id + } +}] + +@description('The resource group the private DNS zone was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the private DNS zone') +output name string = privateDnsZone.name + +@description('The resource ID of the private DNS zone') +output resourceId string = privateDnsZone.id diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/readme.md new file mode 100644 index 000000000..bfa77e582 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/readme.md @@ -0,0 +1,119 @@ +# Private DNS Zones `[Microsoft.Network/privateDnsZones]` + +This template deploys a private DNS zone. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateDnsZones` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/A` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/AAAA` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/CNAME` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/MX` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/PTR` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/SOA` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/SRV` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/TXT` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `a` | _[a](a/readme.md)_ array | `[]` | | Array of A records. | +| `aaaa` | _[aaaa](aaaa/readme.md)_ array | `[]` | | Array of AAAA records. | +| `cname` | _[cname](cname/readme.md)_ array | `[]` | | Array of CNAME records. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `'global'` | | The location of the PrivateDNSZone. Should be global. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `mx` | _[mx](mx/readme.md)_ array | `[]` | | Array of MX records. | +| `ptr` | _[ptr](ptr/readme.md)_ array | `[]` | | Array of PTR records. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `soa` | _[soa](soa/readme.md)_ array | `[]` | | Array of SOA records. | +| `srv` | _[srv](srv/readme.md)_ array | `[]` | | Array of SRV records. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `txt` | _[txt](txt/readme.md)_ array | `[]` | | Array of TXT records. | +| `virtualNetworkLinks` | _[virtualNetworkLinks](virtualNetworkLinks/readme.md)_ array | `[]` | | Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'vnetResourceId' and 'registrationEnabled'. The 'vnetResourceId' is a resource ID of a vNet to link, 'registrationEnabled' (bool) enables automatic DNS registration in the zone for the linked vNet. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private DNS zone | +| `resourceGroupName` | string | The resource group the private DNS zone was deployed into | +| `resourceId` | string | The resource ID of the private DNS zone | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privatednszones](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones) +- [Privatednszones/A](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/A) +- [Privatednszones/AAAA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/AAAA) +- [Privatednszones/CNAME](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/CNAME) +- [Privatednszones/MX](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/MX) +- [Privatednszones/PTR](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/PTR) +- [Privatednszones/SOA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SOA) +- [Privatednszones/SRV](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SRV) +- [Privatednszones/TXT](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/TXT) +- [Privatednszones/Virtualnetworklinks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/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/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep new file mode 100644 index 000000000..4785655fa --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep @@ -0,0 +1,58 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Optional. The name of the virtual network link.') +param name string = '${last(split(virtualNetworkResourceId, '/'))}-vnetlink' + +@description('Optional. The location of the PrivateDNSZone. Should be global.') +param location string = 'global' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?') +param registrationEnabled bool = false + +@description('Required. Link to another virtual network resource ID.') +param virtualNetworkResourceId string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource virtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { + name: name + parent: privateDnsZone + location: location + tags: tags + properties: { + registrationEnabled: registrationEnabled + virtualNetwork: { + id: virtualNetworkResourceId + } + } +} + +@description('The name of the deployed virtual network link') +output name string = virtualNetworkLink.name + +@description('The resource ID of the deployed virtual network link') +output resourceId string = virtualNetworkLink.id + +@description('The resource group of the deployed virtual network link') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md b/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md new file mode 100644 index 000000000..1799010e4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md @@ -0,0 +1,63 @@ +# Private DNS Zone Virtual Network Link `[Microsoft.Network/privateDnsZones/virtualNetworkLinks]` + +This module deploys private dns zone virtual network links. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateDnsZoneName` | string | Private DNS zone name. | +| `virtualNetworkResourceId` | string | Link to another virtual network resource ID. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `'global'` | The location of the PrivateDNSZone. Should be global. | +| `name` | string | `[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]` | The name of the virtual network link. | +| `registrationEnabled` | bool | `False` | Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled? | +| `tags` | object | `{object}` | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed virtual network link | +| `resourceGroupName` | string | The resource group of the deployed virtual network link | +| `resourceId` | string | The resource ID of the deployed virtual network link | + +## Template references + +- [Privatednszones/Virtualnetworklinks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) diff --git a/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/version.json b/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateDnsZones/virtualNetworkLinks/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/carml/1.0.1/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep b/carml/1.0.1/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e92085961 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateEndpoint.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: privateEndpoint +}] diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json new file mode 100644 index 000000000..bfe13c34e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pe-kvlt-min-001" + }, + "targetSubnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + }, + "serviceResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-pe" + }, + "groupId": { + "value": [ + "vault" + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/privateEndpoints/.parameters/parameters.json new file mode 100644 index 000000000..5b5f6f17b --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/.parameters/parameters.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pe-kvlt-001" + }, + "targetSubnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + }, + "serviceResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-pe" + }, + "groupId": { + "value": [ + "vault" + ] + }, + "privateDnsZoneGroups": { + "value": [ + { + "privateDNSResourceIds": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateEndpoints/deploy.bicep new file mode 100644 index 000000000..fc5fb0418 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/deploy.bicep @@ -0,0 +1,105 @@ +@description('Required. Name of the private endpoint resource to create.') +param name string + +@description('Required. Resource ID of the subnet where the endpoint needs to be created.') +param targetSubnetResourceId string + +@description('Required. Resource ID of the resource that needs to be connected to the network.') +param serviceResourceId string + +@description('Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to.') +param groupId array + +@description('Optional. Array of Private DNS zone groups configuration on the private endpoint.') +param privateDnsZoneGroups array = [] + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags to be applied on all resources/resource groups in this deployment.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: serviceResourceId + groupIds: groupId + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: targetSubnetResourceId + } + customDnsConfigs: [] + } +} + +module privateEndpoint_privateDnsZoneGroups 'privateDnsZoneGroups/deploy.bicep' = [for (privateDnsZoneGroup, index) in privateDnsZoneGroups: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-PrivateDnsZoneGroup-${index}' + params: { + privateDNSResourceIds: privateDnsZoneGroup.privateDNSResourceIds + privateEndpointName: privateEndpoint.name + } +}] + +resource privateEndpoint_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateEndpoint.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateEndpoint +} + +module privateEndpoint_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateEndpoint.id + } +}] + +@description('The resource group the private endpoint was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the private endpoint') +output resourceId string = privateEndpoint.id + +@description('The name of the private endpoint') +output name string = privateEndpoint.name diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep b/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep new file mode 100644 index 000000000..04ea26d87 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. The name of the private endpoint') +param privateEndpointName string + +@description('Required. List of private DNS resource IDs') +param privateDNSResourceIds array + +@description('Optional. The name of the private DNS Zone Group') +param name string = 'default' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var privateDnsZoneConfigs = [for privateDNSResourceId in privateDNSResourceIds: { + name: privateEndpointName + properties: { + privateDnsZoneId: privateDNSResourceId + } +}] + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' existing = { + name: privateEndpointName +} + +resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = { + name: name + parent: privateEndpoint + properties: { + privateDnsZoneConfigs: privateDnsZoneConfigs + } +} + +@description('The name of the private endpoint DNS zone group') +output name string = privateDnsZoneGroup.name + +@description('The resource ID of the private endpoint DNS zone group') +output resourceId string = privateDnsZoneGroup.id + +@description('The resource group the private endpoint DNS zone group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md b/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md new file mode 100644 index 000000000..ae4c4219f --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md @@ -0,0 +1,43 @@ +# Network Private Endpoint Private DNS Zone Group `[Microsoft.Network/privateEndpoints/privateDnsZoneGroups]` + +This module deploys a private endpoint private DNS zone group + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateDNSResourceIds` | array | List of private DNS resource IDs | +| `privateEndpointName` | string | The name of the private endpoint | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the private DNS Zone Group | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private endpoint DNS zone group | +| `resourceGroupName` | string | The resource group the private endpoint DNS zone group was deployed into | +| `resourceId` | string | The resource ID of the private endpoint DNS zone group | + +## Template references + +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/version.json b/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/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/carml/1.0.1/Microsoft.Network/privateEndpoints/readme.md b/carml/1.0.1/Microsoft.Network/privateEndpoints/readme.md new file mode 100644 index 000000000..224aecd62 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/readme.md @@ -0,0 +1,108 @@ +# Private Endpoints `[Microsoft.Network/privateEndpoints]` + +This template deploys a private endpoint for a generic service. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource: + +- `PrivateDNSZone` +- `VirtualNetwork/subnet` +- The service that needs to be connected through private endpoint + +**Important**: Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `groupId` | array | Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to. | +| `name` | string | Name of the private endpoint resource to create. | +| `serviceResourceId` | string | Resource ID of the resource that needs to be connected to the network. | +| `targetSubnetResourceId` | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateDnsZoneGroups` | _[privateDnsZoneGroups](privateDnsZoneGroups/readme.md)_ array | `[]` | | Array of Private DNS zone groups configuration on the private endpoint. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags to be applied on all resources/resource groups in this deployment. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private endpoint | +| `resourceGroupName` | string | The resource group the private endpoint was deployed into | +| `resourceId` | string | The resource ID of the private endpoint | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/privateEndpoints/version.json b/carml/1.0.1/Microsoft.Network/privateEndpoints/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/privateEndpoints/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/carml/1.0.1/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e6e4397f3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpAddress +}] diff --git a/carml/1.0.1/Microsoft.Network/publicIPAddresses/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/publicIPAddresses/.parameters/parameters.json new file mode 100644 index 000000000..1e12e533b --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPAddresses/.parameters/parameters.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pip-x-001" + }, + "skuName": { + "value": "Standard" + }, + "publicIPAllocationMethod": { + "value": "Static" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/publicIPAddresses/deploy.bicep b/carml/1.0.1/Microsoft.Network/publicIPAddresses/deploy.bicep new file mode 100644 index 000000000..cb6f57cfa --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPAddresses/deploy.bicep @@ -0,0 +1,194 @@ +@description('Required. The name of the Public IP Address') +param name string + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. The public IP address allocation method.') +@allowed([ + 'Dynamic' + 'Static' +]) +param publicIPAllocationMethod string = 'Dynamic' + +@description('Optional. Name of a public IP address SKU.') +@allowed([ + 'Basic' + 'Standard' +]) +param skuName string = 'Basic' + +@description('Optional. Tier of a public IP address SKU.') +@allowed([ + 'Global' + 'Regional' +]) +param skuTier string = 'Regional' + +@description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from.') +param zones array = [] + +@description('Optional. IP address version.') +@allowed([ + 'IPv4' + 'IPv6' +]) +param publicIPAddressVersion string = 'IPv4' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIPPrefix = { + id: publicIPPrefixResourceId +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + zones: zones + properties: { + publicIPAddressVersion: publicIPAddressVersion + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + idleTimeoutInMinutes: 4 + ipTags: [] + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PIPAddress-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The resource group the public IP address was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address') +output resourceId string = publicIpAddress.id + +@description('The public IP address of the of the public IP address resource') +output ipAddress string = publicIpAddress.properties.ipAddress diff --git a/carml/1.0.1/Microsoft.Network/publicIPAddresses/readme.md b/carml/1.0.1/Microsoft.Network/publicIPAddresses/readme.md new file mode 100644 index 000000000..62ee6c684 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPAddresses/readme.md @@ -0,0 +1,107 @@ +# Public IP Addresses `[Microsoft.Network/publicIPAddresses]` + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Public IP Address | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicIPAddressVersion` | string | `'IPv4'` | `[IPv4, IPv6]` | IP address version. | +| `publicIPAllocationMethod` | string | `'Dynamic'` | `[Dynamic, Static]` | The public IP address allocation method. | +| `publicIPPrefixResourceId` | string | `''` | | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuName` | string | `'Basic'` | `[Basic, Standard]` | Name of a public IP address SKU. | +| `skuTier` | string | `'Regional'` | `[Global, Regional]` | Tier of a public IP address SKU. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `zones` | array | `[]` | | A list of availability zones denoting the IP allocated for the resource needs to come from. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `ipAddress` | string | The public IP address of the of the public IP address resource | +| `name` | string | The name of the public IP address | +| `resourceGroupName` | string | The resource group the public IP address was deployed into | +| `resourceId` | string | The resource ID of the public IP address | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/publicIPAddresses/version.json b/carml/1.0.1/Microsoft.Network/publicIPAddresses/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPAddresses/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/carml/1.0.1/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..fddcae250 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpPrefix.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpPrefix +}] diff --git a/carml/1.0.1/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json new file mode 100644 index 000000000..5b4074820 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pippfx-x-001" + }, + "prefixLength": { + "value": 28 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/publicIPPrefixes/deploy.bicep b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/deploy.bicep new file mode 100644 index 000000000..82f8b7b8a --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/deploy.bicep @@ -0,0 +1,82 @@ +@description('Required. Name of the Public IP Prefix') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Length of the Public IP Prefix') +@minValue(28) +@maxValue(31) +param prefixLength int + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: { + publicIPAddressVersion: 'IPv4' + prefixLength: prefixLength + } +} + +resource publicIpPrefix_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpPrefix.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpPrefix +} + +module publicIpPrefix_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PIPPrefix-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpPrefix.id + } +}] + +@description('The resource ID of the public IP prefix') +output resourceId string = publicIpPrefix.id + +@description('The resource group the public IP prefix was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP prefix') +output name string = publicIpPrefix.name diff --git a/carml/1.0.1/Microsoft.Network/publicIPPrefixes/readme.md b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/readme.md new file mode 100644 index 000000000..e1b27aa1d --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/readme.md @@ -0,0 +1,93 @@ +# Public IP Prefixes `[Microsoft.Network/publicIPPrefixes]` + +This template deploys a public IP prefix. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/publicIPPrefixes` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Public IP Prefix | +| `prefixLength` | int | Length of the Public IP Prefix | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the public IP prefix | +| `resourceGroupName` | string | The resource group the public IP prefix was deployed into | +| `resourceId` | string | The resource ID of the public IP prefix | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipprefixes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPPrefixes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Network/publicIPPrefixes/version.json b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/publicIPPrefixes/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/carml/1.0.1/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..105d1a0ba --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource routeTable 'Microsoft.Network/routeTables@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(routeTable.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: routeTable +}] diff --git a/carml/1.0.1/Microsoft.Network/routeTables/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/routeTables/.parameters/parameters.json new file mode 100644 index 000000000..edd5dba92 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/routeTables/.parameters/parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-udr-x-001" + }, + "routes": { + "value": [ + { + "name": "default", + "properties": { + "addressPrefix": "0.0.0.0/0", + "nextHopType": "VirtualAppliance", + "nextHopIpAddress": "172.16.0.20" + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/routeTables/deploy.bicep b/carml/1.0.1/Microsoft.Network/routeTables/deploy.bicep new file mode 100644 index 000000000..774aa9571 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/routeTables/deploy.bicep @@ -0,0 +1,79 @@ +@description('Required. Name given for the hub route table.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. An Array of Routes to be established within the hub route table.') +param routes array = [] + +@description('Optional. Switch to disable BGP route propagation.') +param disableBgpRoutePropagation bool = false + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource routeTable 'Microsoft.Network/routeTables@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + routes: routes + disableBgpRoutePropagation: disableBgpRoutePropagation + } +} + +resource routeTable_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${routeTable.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: routeTable +} + +module routeTable_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RouteTable-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: routeTable.id + } +}] + +@description('The resource group the route table was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the route table') +output name string = routeTable.name + +@description('The resource ID of the route table') +output resourceId string = routeTable.id diff --git a/carml/1.0.1/Microsoft.Network/routeTables/readme.md b/carml/1.0.1/Microsoft.Network/routeTables/readme.md new file mode 100644 index 000000000..cf448745c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/routeTables/readme.md @@ -0,0 +1,136 @@ +# Route Tables `[Microsoft.Network/routeTables]` + +This module deploys a user defined route table. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/routeTables` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name given for the hub route table. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `disableBgpRoutePropagation` | bool | `False` | | Switch to disable BGP route propagation. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `routes` | array | `[]` | | An Array of Routes to be established within the hub route table. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `routes` + +The `routes` parameter accepts a JSON Array of Route objects to deploy to the Route Table. + +Here's an example of specifying a few routes: + +```json +"routes": { + "value": [ + { + "name": "tojumpboxes", + "properties": { + "addressPrefix": "172.16.0.48/28", + "nextHopType": "VnetLocal" + } + }, + { + "name": "tosharedservices", + "properties": { + "addressPrefix": "172.16.0.64/27", + "nextHopType": "VnetLocal" + } + }, + { + "name": "toonprem", + "properties": { + "addressPrefix": "10.0.0.0/8", + "nextHopType": "VirtualNetworkGateway" + } + }, + { + "name": "tonva", + "properties": { + "addressPrefix": "172.16.0.0/18", + "nextHopType": "VirtualAppliance", + "nextHopIpAddress": "172.16.0.20" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the route table | +| `resourceGroupName` | string | The resource group the route table was deployed into | +| `resourceId` | string | The resource ID of the route table | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Routetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/routeTables) diff --git a/carml/1.0.1/Microsoft.Network/routeTables/version.json b/carml/1.0.1/Microsoft.Network/routeTables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/routeTables/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/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6056c70be --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource trafficmanagerprofile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(trafficmanagerprofile.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: trafficmanagerprofile +}] diff --git a/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json new file mode 100644 index 000000000..fd3469ed6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "tm-000001" + }, + "relativeName": { + "value": "tm-000001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/deploy.bicep b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/deploy.bicep new file mode 100644 index 000000000..10eb3a517 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/deploy.bicep @@ -0,0 +1,191 @@ +@description('Required. Name of the Traffic Manager') +@minLength(1) +param name string + +@description('Optional. The status of the Traffic Manager profile.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param profileStatus string = 'Enabled' + +@description('Optional. The traffic routing method of the Traffic Manager profile.') +@allowed([ + 'Performance' + 'Priority' + 'Weighted' + 'Geographic' + 'MultiValue' + 'Subnet' +]) +param trafficRoutingMethod string = 'Performance' + +@description('Required. The relative DNS name provided by this Traffic Manager profile. This value is combined with the DNS domain name used by Azure Traffic Manager to form the fully-qualified domain name (FQDN) of the profile.') +param relativeName string + +@description('Optional. The DNS Time-To-Live (TTL), in seconds. This informs the local DNS resolvers and DNS clients how long to cache DNS responses provided by this Traffic Manager profile.') +param ttl int = 60 + +@description('Optional. The endpoint monitoring settings of the Traffic Manager profile.') +param monitorConfig object = { + protocol: 'http' + port: '80' + path: '/' +} + +@description('Optional. The list of endpoints in the Traffic Manager profile.') +param endpoints array = [] + +@description('Optional. Indicates whether Traffic View is \'Enabled\' or \'Disabled\' for the Traffic Manager profile. Null, indicates \'Disabled\'. Enabling this feature will increase the cost of the Traffic Manage profile.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param trafficViewEnrollmentStatus string = 'Disabled' + +@description('Optional. Maximum number of endpoints to be returned for MultiValue routing type.') +param maxReturn int = 1 + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ProbeHealthStatusEvents' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ProbeHealthStatusEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' = { + name: name + tags: tags + location: 'global' + properties: { + profileStatus: profileStatus + trafficRoutingMethod: trafficRoutingMethod + dnsConfig: { + relativeName: relativeName + ttl: ttl + } + monitorConfig: monitorConfig + endpoints: endpoints + trafficViewEnrollmentStatus: trafficViewEnrollmentStatus + maxReturn: maxReturn + } +} + +resource trafficManagerProfile_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${trafficManagerProfile.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: trafficManagerProfile +} + +resource trafficManagerProfile_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: trafficManagerProfile +} + +module trafficManagerProfile_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name)}-TrafficManagerProfile-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: trafficManagerProfile.id + } +}] + +@description('The resource ID of the traffix manager') +output resourceId string = trafficManagerProfile.id + +@description('The resource group the traffix manager was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the traffix manager was deployed into') +output name string = trafficManagerProfile.name diff --git a/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/readme.md b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/readme.md new file mode 100644 index 000000000..bc48174e2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/readme.md @@ -0,0 +1,147 @@ +# Traffic Manager Profiles `[Microsoft.Network/trafficmanagerprofiles]` + +This module deploys a traffic manager profile. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/trafficmanagerprofiles` | 2018-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Traffic Manager | +| `relativeName` | string | The relative DNS name provided by this Traffic Manager profile. This value is combined with the DNS domain name used by Azure Traffic Manager to form the fully-qualified domain name (FQDN) of the profile. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ProbeHealthStatusEvents]` | `[ProbeHealthStatusEvents]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endpoints` | array | `[]` | | The list of endpoints in the Traffic Manager profile. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxReturn` | int | `1` | | Maximum number of endpoints to be returned for MultiValue routing type. | +| `monitorConfig` | object | `{object}` | | The endpoint monitoring settings of the Traffic Manager profile. | +| `profileStatus` | string | `'Enabled'` | `[Enabled, Disabled]` | The status of the Traffic Manager profile. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Resource tags. | +| `trafficRoutingMethod` | string | `'Performance'` | `[Performance, Priority, Weighted, Geographic, MultiValue, Subnet]` | The traffic routing method of the Traffic Manager profile. | +| `trafficViewEnrollmentStatus` | string | `'Disabled'` | `[Disabled, Enabled]` | Indicates whether Traffic View is 'Enabled' or 'Disabled' for the Traffic Manager profile. Null, indicates 'Disabled'. Enabling this feature will increase the cost of the Traffic Manage profile. | +| `ttl` | int | `60` | | The DNS Time-To-Live (TTL), in seconds. This informs the local DNS resolvers and DNS clients how long to cache DNS responses provided by this Traffic Manager profile. | + + +### Parameter Usage: `monitorConfig` + +```json +"monitorConfig": { + "value": + { + "protocol": "http", + "port": "80", + "path": "/" + } +} +``` + +### Parameter Usage: `endpoints` + +```json +"endpoints": { + "value": + [ + { + "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/trafficManagerProfiles//azureEndpoints/", + "name": "MyEndpoint001", + "type": "Microsoft.Network/trafficManagerProfiles/azureEndpoints", + "properties": + { + "endpointStatus": "Enabled", + "endpointMonitorStatus": "CheckingEndpoint", + "targetResourceId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/publicIPAddresses/", + "target": "my-pip-001.eastus.cloudapp.azure.com", + "weight": 1, + "priority": 1, + "endpointLocation": "East US" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the traffix manager was deployed into | +| `resourceGroupName` | string | The resource group the traffix manager was deployed into | +| `resourceId` | string | The resource ID of the traffix manager | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Trafficmanagerprofiles](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2018-08-01/trafficmanagerprofiles) diff --git a/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/version.json b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/trafficmanagerprofiles/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/carml/1.0.1/Microsoft.Network/virtualHubs/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/virtualHubs/.parameters/min.parameters.json new file mode 100644 index 000000000..dbe2fa650 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/.parameters/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": { + "name": { + "value": "<>-az-vhub-min-001" + }, + "addressPrefix": { + "value": "10.0.0.0/16" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/adp-<>-az-vw-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/virtualHubs/.parameters/parameters.json new file mode 100644 index 000000000..ed856582a --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/.parameters/parameters.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vhub-x-001" + }, + "addressPrefix": { + "value": "10.1.0.0/16" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/adp-<>-az-vw-x-001" + }, + "hubRouteTables": { + "value": [ + { + "name": "routeTable1" + } + ] + }, + "hubVirtualNetworkConnections": { + "value": [ + { + "name": "connection1", + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-vhub", + "routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vHub-x-001/hubRouteTables/routeTable1" + }, + "propagatedRouteTables": { + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vHub-x-001/hubRouteTables/routeTable1" + } + ], + "labels": [ + "none" + ] + } + } + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualHubs/deploy.bicep new file mode 100644 index 000000000..0cb1f40f6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/deploy.bicep @@ -0,0 +1,171 @@ +@description('Required. The virtual hub name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Required. Address-prefix for this VirtualHub.') +param addressPrefix string + +@description('Optional. Flag to control transit for VirtualRouter hub.') +param allowBranchToBranchTraffic bool = true + +@description('Optional. Resource ID of the Azure Firewall to link to') +param azureFirewallId string = '' + +@description('Optional. Resource ID of the Express Route Gateway to link to') +param expressRouteGatewayId string = '' + +@description('Optional. Resource ID of the Point-to-Site VPN Gateway to link to') +param p2SVpnGatewayId string = '' + +@description('Optional. The preferred routing gateway types') +@allowed([ + 'ExpressRoute' + 'None' + 'VpnGateway' + '' +]) +param preferredRoutingGateway string = '' + +@description('Optional. VirtualHub route tables') +param routeTableRoutes array = [] + +@description('Optional. ID of the Security Partner Provider to link to') +param securityPartnerProviderId string = '' + +@description('Optional. The Security Provider name.') +param securityProviderName string = '' + +@allowed([ + 'Basic' + 'Standard' +]) +@description('Optional. The sku of this VirtualHub.') +param sku string = 'Standard' + +@description('Optional. List of all virtual hub route table v2s associated with this VirtualHub.') +param virtualHubRouteTableV2s array = [] + +@description('Optional. VirtualRouter ASN.') +param virtualRouterAsn int = -1 + +@description('Optional. VirtualRouter IPs.') +param virtualRouterIps array = [] + +@description('Required. Resource ID of the virtual WAN to link to') +param virtualWanId string + +@description('Optional. Resource ID of the VPN Gateway to link to') +param vpnGatewayId string = '' + +@description('Optional. Route tables to create for the virtual hub.') +param hubRouteTables array = [] + +@description('Optional. Virtual network connections to create for the virtual hub.') +param hubVirtualNetworkConnections array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressPrefix: addressPrefix + allowBranchToBranchTraffic: allowBranchToBranchTraffic + azureFirewall: !empty(azureFirewallId) ? { + id: azureFirewallId + } : null + expressRouteGateway: !empty(expressRouteGatewayId) ? { + id: expressRouteGatewayId + } : null + p2SVpnGateway: !empty(p2SVpnGatewayId) ? { + id: p2SVpnGatewayId + } : null + preferredRoutingGateway: !empty(preferredRoutingGateway) ? any(preferredRoutingGateway) : null + routeTable: !empty(routeTableRoutes) ? { + routes: routeTableRoutes + } : null + securityPartnerProvider: !empty(securityPartnerProviderId) ? { + id: securityPartnerProviderId + } : null + securityProviderName: securityProviderName + sku: sku + virtualHubRouteTableV2s: virtualHubRouteTableV2s + virtualRouterAsn: virtualRouterAsn != -1 ? virtualRouterAsn : null + virtualRouterIps: !empty(virtualRouterIps) ? virtualRouterIps : null + virtualWan: { + id: virtualWanId + } + vpnGateway: !empty(vpnGatewayId) ? { + id: vpnGatewayId + } : null + } +} + +resource virtualHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualHub.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualHub +} + +module virtualHub_routeTables 'hubRouteTables/deploy.bicep' = [for (routeTable, index) in hubRouteTables: { + name: '${uniqueString(deployment().name, location)}-routeTable-${index}' + params: { + virtualHubName: virtualHub.name + name: routeTable.name + labels: contains(routeTable, 'labels') ? routeTable.labels : [] + routes: contains(routeTable, 'routes') ? routeTable.routes : [] + } +}] + +module virtualHub_hubVirtualNetworkConnections 'hubVirtualNetworkConnections/deploy.bicep' = [for (virtualNetworkConnection, index) in hubVirtualNetworkConnections: { + name: '${uniqueString(deployment().name, location)}-connection-${index}' + params: { + virtualHubName: virtualHub.name + name: virtualNetworkConnection.name + enableInternetSecurity: contains(virtualNetworkConnection, 'enableInternetSecurity') ? virtualNetworkConnection.enableInternetSecurity : true + remoteVirtualNetworkId: virtualNetworkConnection.remoteVirtualNetworkId + routingConfiguration: contains(virtualNetworkConnection, 'routingConfiguration') ? virtualNetworkConnection.routingConfiguration : {} + } + dependsOn: [ + virtualHub_routeTables + ] +}] + +@description('The resource group the virtual hub was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual hub') +output resourceId string = virtualHub.id + +@description('The name of the virtual hub') +output name string = virtualHub.name diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep new file mode 100644 index 000000000..221a76f44 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. The route table name.') +param name string + +@description('Required. The virtual hub name.') +param virtualHubName string + +@description('Optional. List of labels associated with this route table.') +param labels array = [] + +@description('Optional. List of all routes.') +param routes array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' existing = { + name: virtualHubName +} + +resource hubRouteTable 'Microsoft.Network/virtualHubs/hubRouteTables@2021-05-01' = { + name: name + parent: virtualHub + properties: { + labels: !empty(labels) ? labels : null + routes: !empty(routes) ? routes : null + } +} + +@description('The name of the deployed virtual hub route table') +output name string = hubRouteTable.name + +@description('The resource ID of the deployed virtual hub route table') +output resourceId string = hubRouteTable.id + +@description('The resource group the virtual hub route table was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/readme.md b/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/readme.md new file mode 100644 index 000000000..e34e97187 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/readme.md @@ -0,0 +1,44 @@ +# Virtual Hub Route Table `[Microsoft.Network/virtualHubs/hubRouteTables]` + +This module deploys virtual hub route tables. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs/hubRouteTables` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The route table name. | +| `virtualHubName` | string | The virtual hub name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `labels` | array | `[]` | List of labels associated with this route table. | +| `routes` | array | `[]` | List of all routes. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed virtual hub route table | +| `resourceGroupName` | string | The resource group the virtual hub route table was deployed into | +| `resourceId` | string | The resource ID of the deployed virtual hub route table | + +## Template references + +- [Virtualhubs/Hubroutetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubRouteTables) diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/version.json b/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/hubRouteTables/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/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep new file mode 100644 index 000000000..02d97d7e7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep @@ -0,0 +1,54 @@ +@description('Required. The connection name.') +param name string + +@description('Required. The virtual hub name.') +param virtualHubName string + +@description('Optional. Enable internet security.') +param enableInternetSecurity bool = true + +@description('Required. Resource ID of the virtual network to link to') +param remoteVirtualNetworkId string + +@description('Optional. Routing Configuration indicating the associated and propagated route tables for this connection.') +param routingConfiguration object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' existing = { + name: virtualHubName +} + +resource hubVirtualNetworkConnection 'Microsoft.Network/virtualHubs/hubVirtualNetworkConnections@2021-05-01' = { + name: name + parent: virtualHub + properties: { + enableInternetSecurity: enableInternetSecurity + remoteVirtualNetwork: { + id: remoteVirtualNetworkId + } + routingConfiguration: !empty(routingConfiguration) ? routingConfiguration : null + } +} + +@description('The resource group the virtual hub connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual hub connection') +output resourceId string = hubVirtualNetworkConnection.id + +@description('The name of the virtual hub connection') +output name string = hubVirtualNetworkConnection.name diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md b/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md new file mode 100644 index 000000000..adc589d13 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md @@ -0,0 +1,49 @@ +# Virtual Hub Virtual Network Connections `[Microsoft.Network/virtualHubs/hubVirtualNetworkConnections]` + +This module deploys virtual hub virtual network connections. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The connection name. | +| `remoteVirtualNetworkId` | string | Resource ID of the virtual network to link to | +| `virtualHubName` | string | The virtual hub name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableInternetSecurity` | bool | `True` | Enable internet security. | +| `routingConfiguration` | object | `{object}` | Routing Configuration indicating the associated and propagated route tables for this connection. | + + +### Parameter Usage: `hubVirtualNetworkConnections` + +... + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual hub connection | +| `resourceGroupName` | string | The resource group the virtual hub connection was deployed into | +| `resourceId` | string | The resource ID of the virtual hub connection | + +## Template references + +- [Virtualhubs/Hubvirtualnetworkconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubVirtualNetworkConnections) diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/version.json b/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/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/carml/1.0.1/Microsoft.Network/virtualHubs/readme.md b/carml/1.0.1/Microsoft.Network/virtualHubs/readme.md new file mode 100644 index 000000000..96585d28e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/readme.md @@ -0,0 +1,84 @@ +# Virtual Hubs `[Microsoft.Network/virtualHubs]` + +This module deploys a Virtual Hub. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/virtualHubs` | 2021-05-01 | +| `Microsoft.Network/virtualHubs/hubRouteTables` | 2021-05-01 | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `addressPrefix` | string | Address-prefix for this VirtualHub. | +| `name` | string | The virtual hub name. | +| `virtualWanId` | string | Resource ID of the virtual WAN to link to | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBranchToBranchTraffic` | bool | `True` | | Flag to control transit for VirtualRouter hub. | +| `azureFirewallId` | string | `''` | | Resource ID of the Azure Firewall to link to | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `expressRouteGatewayId` | string | `''` | | Resource ID of the Express Route Gateway to link to | +| `hubRouteTables` | _[hubRouteTables](hubRouteTables/readme.md)_ array | `[]` | | Route tables to create for the virtual hub. | +| `hubVirtualNetworkConnections` | _[hubVirtualNetworkConnections](hubVirtualNetworkConnections/readme.md)_ array | `[]` | | Virtual network connections to create for the virtual hub. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `p2SVpnGatewayId` | string | `''` | | Resource ID of the Point-to-Site VPN Gateway to link to | +| `preferredRoutingGateway` | string | `''` | `[ExpressRoute, None, VpnGateway, ]` | The preferred routing gateway types | +| `routeTableRoutes` | array | `[]` | | VirtualHub route tables | +| `securityPartnerProviderId` | string | `''` | | ID of the Security Partner Provider to link to | +| `securityProviderName` | string | `''` | | The Security Provider name. | +| `sku` | string | `'Standard'` | `[Basic, Standard]` | The sku of this VirtualHub. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `virtualHubRouteTableV2s` | array | `[]` | | List of all virtual hub route table v2s associated with this VirtualHub. | +| `virtualRouterAsn` | int | `-1` | | VirtualRouter ASN. | +| `virtualRouterIps` | array | `[]` | | VirtualRouter IPs. | +| `vpnGatewayId` | string | `''` | | Resource ID of the VPN Gateway to link to | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual hub | +| `resourceGroupName` | string | The resource group the virtual hub was deployed into | +| `resourceId` | string | The resource ID of the virtual hub | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Virtualhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs) +- [Virtualhubs/Hubroutetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubRouteTables) +- [Virtualhubs/Hubvirtualnetworkconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubVirtualNetworkConnections) diff --git a/carml/1.0.1/Microsoft.Network/virtualHubs/version.json b/carml/1.0.1/Microsoft.Network/virtualHubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualHubs/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/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5c5daeab2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualNetworkGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualNetworkGateway +}] diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json new file mode 100644 index 000000000..15f8bd233 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-gw-er-001" + }, + "gatewayPipName": { + "value": [ + "<>-az-gw-er-001-pip" + ] + }, + "domainNameLabel": { + "value": [ + "<>-az-gw-er-dm-001" + ] + }, + "virtualNetworkGatewayType": { + "value": "ExpressRoute" + }, + "virtualNetworkGatewaySku": { + "value": "ErGw1AZ" + }, + "vNetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "tags": { + "value": { + "Environment": "Validation", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "", + "CostCenter": "", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.parameters.json b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.parameters.json new file mode 100644 index 000000000..243053f3a --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.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": "<>-az-gw-vpn-001" + }, + "domainNameLabel": { + "value": [ + "<>-az-gw-vpn-dm-001" + ] + }, + "virtualNetworkGatewayType": { + "value": "Vpn" + }, + "virtualNetworkGatewaySku": { + "value": "VpnGw1AZ" + }, + "publicIpZones": { + "value": [ + "1" + ] + }, + "vpnType": { + "value": "RouteBased" + }, + "activeActive": { + "value": false + }, + "vNetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/deploy.bicep new file mode 100644 index 000000000..998c9cdb1 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/deploy.bicep @@ -0,0 +1,403 @@ +@description('Required. Specifies the Virtual Network Gateway name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the name of the Public IP used by the Virtual Network Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the gateway\'s name.') +param gatewayPipName array = [] + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones.') +param publicIpZones array = [] + +@description('Optional. DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com') +param domainNameLabel array = [] + +@description('Required. Specifies the gateway type. E.g. VPN, ExpressRoute') +@allowed([ + 'Vpn' + 'ExpressRoute' +]) +param virtualNetworkGatewayType string + +@description('Required. The Sku of the Gateway.') +@allowed([ + 'Basic' + 'VpnGw1' + 'VpnGw2' + 'VpnGw3' + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'Standard' + 'HighPerformance' + 'UltraPerformance' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +]) +param virtualNetworkGatewaySku string + +@description('Required. Specifies the VPN type') +@allowed([ + 'PolicyBased' + 'RouteBased' +]) +param vpnType string = 'RouteBased' + +@description('Required. Virtual Network resource ID') +param vNetResourceId string + +@description('Optional. Value to specify if the Gateway should be deployed in active-active or active-passive configuration') +param activeActive bool = true + +@description('Optional. Value to specify if BGP is enabled or not') +param enableBgp bool = true + +@description('Optional. ASN value') +param asn int = 65815 + +@description('Optional. The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network.') +param vpnClientAddressPoolPrefix string = '' + +@description('Optional. Client root certificate data used to authenticate VPN clients.') +param clientRootCertData string = '' + +@description('Optional. Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet.') +param clientRevokedCertThumbprint string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param publicIpdiagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'GatewayDiagnosticLog' + 'TunnelDiagnosticLog' + 'RouteDiagnosticLog' + 'IKEDiagnosticLog' + 'P2SDiagnosticLog' +]) +param virtualNetworkGatewaydiagnosticLogCategoriesToEnable array = [ + 'GatewayDiagnosticLog' + 'TunnelDiagnosticLog' + 'RouteDiagnosticLog' + 'IKEDiagnosticLog' + 'P2SDiagnosticLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param virtualNetworkGatewayDiagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. The name of the diagnostic setting, if deployed.') +param publicIpDiagnosticSettingsName string = '${name}-diagnosticSettings' + +var virtualNetworkGatewayDiagnosticsLogs = [for category in virtualNetworkGatewaydiagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIpDiagnosticsLogs = [for category in publicIpdiagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var zoneRedundantSkus = [ + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'VpnGw4AZ' + 'VpnGw5AZ' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +] +var gatewayPipSku = contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? 'Standard' : 'Basic' +var gatewayPipAllocationMethod = contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? 'Static' : 'Dynamic' +var gatewaySubnetId = '${vNetResourceId}/subnets/GatewaySubnet' +var activeActive_var = virtualNetworkGatewayType == 'ExpressRoute' ? false : activeActive + +// Public IP variables +var gatewayPipName1 = length(gatewayPipName) == 0 ? '${name}-pip1' : gatewayPipName[0] +var gatewayPipName2 = activeActive_var ? (length(gatewayPipName) == 1 ? '${name}-pip2' : gatewayPipName[1]) : '' + +var gatewayMultiPipArray = [ + gatewayPipName1 + gatewayPipName2 +] +var gatewaySinglePipArray = [ + gatewayPipName1 +] +var virtualGatewayPipName_var = !empty(gatewayPipName2) ? gatewayMultiPipArray : gatewaySinglePipArray +var gatewayPipId1 = az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName1) +var gatewayPipId2 = activeActive_var ? az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName2) : az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName1) + +var enableBgp_var = virtualNetworkGatewayType == 'ExpressRoute' ? false : enableBgp +var vpnType_var = virtualNetworkGatewayType == 'ExpressRoute' ? 'PolicyBased' : vpnType +var bgpSettings = { + asn: asn +} +var publicIPPrefix = { + id: publicIPPrefixResourceId +} +var activePassiveIpConfiguration = [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: gatewaySubnetId + } + publicIPAddress: { + id: gatewayPipId1 + } + } + name: 'vNetGatewayConfig1' + } +] +var activeActiveIpConfiguration = [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: gatewaySubnetId + } + publicIPAddress: { + id: gatewayPipId1 + } + } + name: 'vNetGatewayConfig1' + } + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: gatewaySubnetId + } + publicIPAddress: { + id: gatewayPipId2 + } + } + name: 'vNetGatewayConfig2' + } +] +var vpnClientRootCertificates = [ + { + name: 'RootCert1' + properties: { + PublicCertData: clientRootCertData + } + } +] +var vpmClientRevokedCertificates = [ + { + name: 'RevokedCert1' + properties: { + Thumbprint: clientRevokedCertThumbprint + } + } +] +var vpnClientConfiguration = { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] + } + vpnClientRootCertificates: !empty(clientRootCertData) ? vpnClientRootCertificates : null + vpnClientRevokedCertificates: !empty(clientRevokedCertThumbprint) ? vpmClientRevokedCertificates : null +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +// Public IPs +// ========== +@batchSize(1) +resource virtualGatewayPublicIP 'Microsoft.Network/publicIPAddresses@2021-05-01' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: { + name: virtualGatewayPublicIpName + location: location + tags: tags + sku: { + name: gatewayPipSku + } + properties: { + publicIPAllocationMethod: gatewayPipAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + dnsSettings: length(virtualGatewayPipName_var) == length(domainNameLabel) ? { + domainNameLabel: domainNameLabel[index] + } : null + } + zones: contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? publicIpZones : null +}] + +@batchSize(1) +resource virtualGatewayPublicIP_lock 'Microsoft.Authorization/locks@2017-04-01' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: if (lock != 'NotSpecified') { + name: '${virtualGatewayPublicIpName}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualGatewayPublicIP[index] +}] + +@batchSize(1) +resource virtualNetworkGatewayPublicIp_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: publicIpDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: publicIpDiagnosticsLogs + } + scope: virtualGatewayPublicIP[index] +}] + +// VNET Gateway +// ============ +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipConfigurations: activeActive_var ? activeActiveIpConfiguration : activePassiveIpConfiguration + activeActive: activeActive_var + enableBgp: enableBgp_var + bgpSettings: enableBgp_var ? bgpSettings : null + sku: { + name: virtualNetworkGatewaySku + tier: virtualNetworkGatewaySku + } + gatewayType: virtualNetworkGatewayType + vpnType: vpnType_var + vpnClientConfiguration: !empty(vpnClientAddressPoolPrefix) ? vpnClientConfiguration : null + } + dependsOn: [ + virtualGatewayPublicIP + ] +} + +resource virtualNetworkGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualNetworkGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualNetworkGateway +} + +resource virtualNetworkGateway_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: virtualNetworkGatewayDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: virtualNetworkGatewayDiagnosticsLogs + } + scope: virtualNetworkGateway +} + +module virtualNetworkGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VNetGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualNetworkGateway.id + } +}] + +@description('The resource group the virtual network gateway was deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network gateway') +output name string = virtualNetworkGateway.name + +@description('The resource ID of the virtual network gateway') +output resourceId string = virtualNetworkGateway.id + +@description('Shows if the virtual network gateway is configured in active-active mode') +output activeActive bool = virtualNetworkGateway.properties.activeActive diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/readme.md b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/readme.md new file mode 100644 index 000000000..078abc908 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/readme.md @@ -0,0 +1,152 @@ +# Virtual Network Gateways `[Microsoft.Network/virtualNetworkGateways]` + +This module deploys a virtual network gateway. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | +| `Microsoft.Network/virtualNetworkGateways` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `name` | string | | | Specifies the Virtual Network Gateway name. | +| `virtualNetworkGatewaySku` | string | | `[Basic, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, VpnGw3AZ, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ]` | The Sku of the Gateway. | +| `virtualNetworkGatewayType` | string | | `[Vpn, ExpressRoute]` | Specifies the gateway type. E.g. VPN, ExpressRoute | +| `vNetResourceId` | string | | | Virtual Network resource ID | +| `vpnType` | string | `'RouteBased'` | `[PolicyBased, RouteBased]` | Specifies the VPN type | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `activeActive` | bool | `True` | | Value to specify if the Gateway should be deployed in active-active or active-passive configuration | +| `asn` | int | `65815` | | ASN value | +| `clientRevokedCertThumbprint` | string | `''` | | Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet. | +| `clientRootCertData` | string | `''` | | Client root certificate data used to authenticate VPN clients. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `domainNameLabel` | array | `[]` | | DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com | +| `enableBgp` | bool | `True` | | Value to specify if BGP is enabled or not | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `gatewayPipName` | array | `[]` | | Specifies the name of the Public IP used by the Virtual Network Gateway. If it's not provided, a '-pip' suffix will be appended to the gateway's name. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicIpdiagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `publicIpDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `publicIPPrefixResourceId` | string | `''` | | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `publicIpZones` | array | `[]` | | Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `virtualNetworkGatewaydiagnosticLogCategoriesToEnable` | array | `[GatewayDiagnosticLog, TunnelDiagnosticLog, RouteDiagnosticLog, IKEDiagnosticLog, P2SDiagnosticLog]` | `[GatewayDiagnosticLog, TunnelDiagnosticLog, RouteDiagnosticLog, IKEDiagnosticLog, P2SDiagnosticLog]` | The name of logs that will be streamed. | +| `virtualNetworkGatewayDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `vpnClientAddressPoolPrefix` | string | `''` | | The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network. | + + +### Parameter Usage: `subnets` + +The `subnets` parameter accepts a JSON Array of `subnet` objects to deploy to the Virtual Network. + +Here's an example of specifying a couple Subnets to deploy: + +```json +"subnets": { + "value": [ + { + "name": "app", + "properties": { + "addressPrefix": "10.1.0.0/24", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'app-nsg')]" + }, + "routeTable": { + "id": "[resourceId('Microsoft.Network/routeTables', 'app-udr')]" + } + } + }, + { + "name": "data", + "properties": { + "addressPrefix": "10.1.1.0/24" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `activeActive` | bool | Shows if the virtual network gateway is configured in active-active mode | +| `name` | string | The name of the virtual network gateway | +| `resourceGroupName` | string | The resource group the virtual network gateway was deployed | +| `resourceId` | string | The resource ID of the virtual network gateway | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworkgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworkGateways) diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/version.json b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworkGateways/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/carml/1.0.1/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b28fa1ee7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep @@ -0,0 +1,70 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualNetwork.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualNetwork +}] diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json new file mode 100644 index 000000000..2d5064277 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-min-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/parameters.json new file mode 100644 index 000000000..294d0ff98 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/parameters.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-x-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + }, + "subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.255.0/24" + }, + { + "name": "<>-az-subnet-x-001", + "addressPrefix": "10.0.0.0/24", + "networkSecurityGroupId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "serviceEndpoints": [ + { + "service": "Microsoft.Storage" + }, + { + "service": "Microsoft.Sql" + } + ], + "routeTableId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/routeTables/adp-<>-az-udr-x-001" + }, + { + "name": "<>-az-subnet-x-002", + "addressPrefix": "10.0.3.0/24", + "delegations": [ + { + "name": "netappDel", + "properties": { + "serviceName": "Microsoft.Netapp/volumes" + } + } + ] + }, + { + "name": "<>-az-subnet-x-003", + "addressPrefix": "10.0.6.0/24", + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + ] + }, + "dnsServers": { + "value": [ + "10.0.1.4", + "10.0.1.5" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json b/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json new file mode 100644 index 000000000..f8faae317 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-peer-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/24" + ] + }, + "subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.0.0/26" + } + ] + }, + "virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-peer01", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "useRemoteGateways": false, + "remotePeeringEnabled": true, + "remotePeeringName": "customName", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringAllowForwardedTraffic": true + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualNetworks/deploy.bicep new file mode 100644 index 000000000..69e57a9b6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/deploy.bicep @@ -0,0 +1,255 @@ +@description('Required. The Virtual Network (vNet) Name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. An Array of 1 or more IP Address Prefixes for the Virtual Network.') +param addressPrefixes array + +@description('Optional. An Array of subnets to deploy to the Virtual Network.') +param subnets array = [] + +@description('Optional. DNS Servers associated to the Virtual Network.') +param dnsServers array = [] + +@description('Optional. Resource ID of the DDoS protection plan to assign the VNET to. If it\'s left blank, DDoS protection will not be configured. If it\'s provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription.') +param ddosProtectionPlanId string = '' + +@description('Optional. Virtual Network Peerings configurations') +param virtualNetworkPeerings array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'VMProtectionAlerts' +]) +param diagnosticLogCategoriesToEnable array = [ + 'VMProtectionAlerts' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var dnsServers_var = { + dnsServers: array(dnsServers) +} +var ddosProtectionPlan = { + id: ddosProtectionPlanId +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressSpace: { + addressPrefixes: addressPrefixes + } + ddosProtectionPlan: !empty(ddosProtectionPlanId) ? ddosProtectionPlan : null + dhcpOptions: !empty(dnsServers) ? dnsServers_var : null + enableDdosProtection: !empty(ddosProtectionPlanId) + subnets: [for subnet in subnets: { + name: subnet.name + properties: { + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIpConfigurations: contains(subnet, 'applicationGatewayIpConfigurations') ? subnet.applicationGatewayIpConfigurations : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGateway: contains(subnet, 'natGatewayId') ? { + 'id': subnet.natGatewayId + } : json('null') + networkSecurityGroup: contains(subnet, 'networkSecurityGroupId') ? { + 'id': subnet.networkSecurityGroupId + } : json('null') + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : null + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : null + routeTable: contains(subnet, 'routeTableId') ? { + 'id': subnet.routeTableId + } : json('null') + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + } + }] + } +} + +//NOTE Start: ------------------------------------ +// The below module (virtualNetwork_subnets) is a duplicate of the child resource (subnets) defined in the parent module (virtualNetwork). +// The reason it exists so that deployment validation tests can be performed on the child module (subnets), in case that module needed to be deployed alone outside of this template. +// The reason for duplication is due to the current design for the (virtualNetworks) resource from Azure, where if the child module (subnets) does not exist within it, causes +// an issue, where the child resource (subnets) gets all of its properties removed, hence not as 'idempotent' as it should be. See https://github.com/Azure/azure-quickstart-templates/issues/2786 for more details. +// You can safely remove the below child module (virtualNetwork_subnets) in your consumption of the module (virtualNetworks) to reduce the template size and duplication. +//NOTE End : ------------------------------------ + +module virtualNetwork_subnets 'subnets/deploy.bicep' = [for (subnet, index) in subnets: { + name: '${uniqueString(deployment().name, location)}-subnet-${index}' + params: { + virtualNetworkName: virtualNetwork.name + name: subnet.name + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIpConfigurations: contains(subnet, 'applicationGatewayIpConfigurations') ? subnet.applicationGatewayIpConfigurations : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGatewayId: contains(subnet, 'natGatewayId') ? subnet.natGatewayId : '' + networkSecurityGroupId: contains(subnet, 'networkSecurityGroupId') ? subnet.networkSecurityGroupId : '' + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : '' + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : '' + routeTableId: contains(subnet, 'routeTableId') ? subnet.routeTableId : '' + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + } +}] + +// Local to Remote peering +module virtualNetwork_peering_local 'virtualNetworkPeerings/deploy.bicep' = [for (peering, index) in virtualNetworkPeerings: { + name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-local-${index}' + params: { + localVnetName: virtualNetwork.name + remoteVirtualNetworkId: peering.remoteVirtualNetworkId + name: contains(peering, 'name') ? peering.name : '${name}-${last(split(peering.remoteVirtualNetworkId, '/'))}' + allowForwardedTraffic: contains(peering, 'allowForwardedTraffic') ? peering.allowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'allowGatewayTransit') ? peering.allowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'allowVirtualNetworkAccess') ? peering.allowVirtualNetworkAccess : true + doNotVerifyRemoteGateways: contains(peering, 'doNotVerifyRemoteGateways') ? peering.doNotVerifyRemoteGateways : true + useRemoteGateways: contains(peering, 'useRemoteGateways') ? peering.useRemoteGateways : false + } +}] + +// Remote to local peering (reverse) +module virtualNetwork_peering_remote 'virtualNetworkPeerings/deploy.bicep' = [for (peering, index) in virtualNetworkPeerings: if (contains(peering, 'remotePeeringEnabled') ? peering.remotePeeringEnabled == true : false) { + name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-remote-${index}' + scope: resourceGroup(split(peering.remoteVirtualNetworkId, '/')[2], split(peering.remoteVirtualNetworkId, '/')[4]) + params: { + localVnetName: last(split(peering.remoteVirtualNetworkId, '/')) + remoteVirtualNetworkId: virtualNetwork.id + name: contains(peering, 'remotePeeringName') ? peering.remotePeeringName : '${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}' + allowForwardedTraffic: contains(peering, 'remotePeeringAllowForwardedTraffic') ? peering.remotePeeringAllowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'remotePeeringAllowGatewayTransit') ? peering.remotePeeringAllowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'remotePeeringAllowVirtualNetworkAccess') ? peering.remotePeeringAllowVirtualNetworkAccess : true + doNotVerifyRemoteGateways: contains(peering, 'remotePeeringDoNotVerifyRemoteGateways') ? peering.remotePeeringDoNotVerifyRemoteGateways : true + useRemoteGateways: contains(peering, 'remotePeeringUseRemoteGateways') ? peering.remotePeeringUseRemoteGateways : false + } +}] + +resource virtualNetwork_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualNetwork.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualNetwork +} + +resource virtualNetwork_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: virtualNetwork +} + +module virtualNetwork_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VNet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualNetwork.id + } +}] + +@description('The resource group the virtual network was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual network') +output resourceId string = virtualNetwork.id + +@description('The name of the virtual network') +output name string = virtualNetwork.name + +@description('The names of the deployed subnets') +output subnetNames array = [for subnet in subnets: subnet.name] + +@description('The resource IDs of the deployed subnets') +output subnetResourceIds array = [for subnet in subnets: az.resourceId('Microsoft.Network/virtualNetworks/subnets', name, subnet.name)] diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/readme.md b/carml/1.0.1/Microsoft.Network/virtualNetworks/readme.md new file mode 100644 index 000000000..daaa1ca6e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/readme.md @@ -0,0 +1,203 @@ +# Virtual Networks `[Microsoft.Network/virtualNetworks]` + +This template deploys a virtual network (vNet). + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Considerations](#Considerations) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/virtualNetworks` | 2021-05-01 | +| `Microsoft.Network/virtualNetworks/subnets` | 2021-05-01 | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `addressPrefixes` | array | An Array of 1 or more IP Address Prefixes for the Virtual Network. | +| `name` | string | The Virtual Network (vNet) Name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `ddosProtectionPlanId` | string | `''` | | Resource ID of the DDoS protection plan to assign the VNET to. If it's left blank, DDoS protection will not be configured. If it's provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[VMProtectionAlerts]` | `[VMProtectionAlerts]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `dnsServers` | array | `[]` | | DNS Servers associated to the Virtual Network. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `subnets` | _[subnets](subnets/readme.md)_ array | `[]` | | An Array of subnets to deploy to the Virtual Network. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `virtualNetworkPeerings` | _[virtualNetworkPeerings](virtualNetworkPeerings/readme.md)_ array | `[]` | | Virtual Network Peerings configurations | + + +### Parameter Usage: `subnets` + +Below you can find an example for the subnet property's usage. For all remaining properties, please refer to the _[subnets](subnets/readme.md)_ readme. + +```json +"subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.255.0/24" + }, + { + "name": "<>-az-subnet-x-001", + "addressPrefix": "10.0.0.0/24", + "networkSecurityGroupId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "serviceEndpoints": [ + { + "service": "Microsoft.Storage" + }, + { + "service": "Microsoft.Sql" + } + ], + "routeTableId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/routeTables/adp-<>-az-udr-x-001", + "delegations": [ + { + "name": "netappDel", + "properties": { + "serviceName": "Microsoft.Netapp/volumes" + } + } + ], + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + ] +} +``` + +### Parameter Usage: `virtualNetworkPeerings` + +As the virtual network peering array allows you to deploy not only a one-way but also two-way peering (i.e reverse), you can use the following ***additional*** properties on top of what is documented in _[virtualNetworkPeerings](virtualNetworkPeerings/readme.md)_. + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `remotePeeringEnabled` | bool | `false` | | Optional. Set to true to also deploy the reverse peering for the configured remote virtual networks to the local network | +| `remotePeeringName` | string | `'${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}'` | | Optional. The Name of Vnet Peering resource. If not provided, default value will be - | +| `remotePeeringAllowForwardedTraffic` | bool | `true` | | Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. | +| `remotePeeringAllowGatewayTransit` | bool | `false` | | Optional. If gateway links can be used in remote virtual networking to link to this virtual network. | +| `remotePeeringAllowVirtualNetworkAccess` | bool | `true` | | Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. | +| `remotePeeringDoNotVerifyRemoteGateways` | bool | `true` | | Optional. If we need to verify the provisioning state of the remote gateway. | +| `remotePeeringUseRemoteGateways` | bool | `false` | | Optional. If remote gateways can be used on this virtual network. If the flag is set to `true`, and allowGatewayTransit on local peering is also `true`, virtual network will use gateways of local virtual network for transit. Only one peering can have this flag set to `true`. This flag cannot be set if virtual network already has a gateway. | + +```json +"virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-peer01", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "useRemoteGateways": false, + "remotePeeringEnabled": true, + "remotePeeringName": "customName", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringAllowForwardedTraffic": true + } + ] +} +``` + +### Parameter Usage: `addressPrefixes` + +The `addressPrefixes` parameter accepts a JSON Array of string values containing the IP Address Prefixes for the Virtual Network (vNet). + +Here's an example of specifying a single Address Prefix: + +```json +"addressPrefixes": { + "value": [ + "10.1.0.0/16" + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Considerations + +The network security group and route table resources must reside in the same resource group as the virtual network. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network | +| `resourceGroupName` | string | The resource group the virtual network was deployed into | +| `resourceId` | string | The resource ID of the virtual network | +| `subnetNames` | array | The names of the deployed subnets | +| `subnetResourceIds` | array | The resource IDs of the deployed subnets | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks) +- [Virtualnetworks/Subnets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/subnets) +- [Virtualnetworks/Virtualnetworkpeerings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/virtualNetworkPeerings) diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/deploy.bicep new file mode 100644 index 000000000..bb13cecca --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/deploy.bicep @@ -0,0 +1,110 @@ +@description('Optional. The Name of the subnet resource.') +param name string + +@description('Required. The name of the parent virtual network') +param virtualNetworkName string + +@description('Required. The address prefix for the subnet.') +param addressPrefix string + +@description('Optional. The resource ID of the network security group to assign to the subnet') +param networkSecurityGroupId string = '' + +@description('Optional. The resource ID of the route table to assign to the subnet') +param routeTableId string = '' + +@description('Optional. The service endpoints to enable on the subnet') +param serviceEndpoints array = [] + +@description('Optional. The delegations to enable on the subnet') +param delegations array = [] + +@description('Optional. The resource ID of the NAT Gateway to use for the subnet') +param natGatewayId string = '' + +@description('Optional. enable or disable apply network policies on private endpoint in the subnet.') +@allowed([ + 'Disabled' + 'Enabled' + '' +]) +param privateEndpointNetworkPolicies string = '' + +@description('Optional. enable or disable apply network policies on private link service in the subnet.') +@allowed([ + 'Disabled' + 'Enabled' + '' +]) +param privateLinkServiceNetworkPolicies string = '' + +@description('Optional. List of address prefixes for the subnet.') +param addressPrefixes array = [] + +@description('Optional. Application gateway IP configurations of virtual network resource.') +param applicationGatewayIpConfigurations array = [] + +@description('Optional. Array of IpAllocation which reference this subnet') +param ipAllocations array = [] + +@description('Optional. An array of service endpoint policies.') +param serviceEndpointPolicies array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: virtualNetworkName +} + +resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-05-01' = { + name: name + parent: virtualNetwork + properties: { + addressPrefix: addressPrefix + networkSecurityGroup: !empty(networkSecurityGroupId) ? { + id: networkSecurityGroupId + } : null + routeTable: !empty(routeTableId) ? { + id: routeTableId + } : null + natGateway: !empty(natGatewayId) ? { + id: natGatewayId + } : null + serviceEndpoints: serviceEndpoints + delegations: delegations + privateEndpointNetworkPolicies: !empty(privateEndpointNetworkPolicies) ? any(privateEndpointNetworkPolicies) : null + privateLinkServiceNetworkPolicies: !empty(privateLinkServiceNetworkPolicies) ? any(privateLinkServiceNetworkPolicies) : null + addressPrefixes: addressPrefixes + applicationGatewayIpConfigurations: applicationGatewayIpConfigurations + ipAllocations: ipAllocations + serviceEndpointPolicies: serviceEndpointPolicies + } +} + +@description('The resource group the virtual network peering was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network peering') +output name string = subnet.name + +@description('The resource ID of the virtual network peering') +output resourceId string = subnet.id + +@description('The address prefix for the subnet') +output subnetAddressPrefix string = subnet.properties.addressPrefix + +@description('List of address prefixes for the subnet') +output subnetAddressPrefixes array = !empty(addressPrefixes) ? subnet.properties.addressPrefixes : [] diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/readme.md b/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/readme.md new file mode 100644 index 000000000..e19e99ecb --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/readme.md @@ -0,0 +1,86 @@ +# Virtual Network Subnets `[Microsoft.Network/virtualNetworks/subnets]` + +This module deploys a virtual network subnet. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Considerations](#Considerations) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualNetworks/subnets` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `addressPrefix` | string | The address prefix for the subnet. | +| `virtualNetworkName` | string | The name of the parent virtual network | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefixes` | array | `[]` | | List of address prefixes for the subnet. | +| `applicationGatewayIpConfigurations` | array | `[]` | | Application gateway IP configurations of virtual network resource. | +| `delegations` | array | `[]` | | The delegations to enable on the subnet | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipAllocations` | array | `[]` | | Array of IpAllocation which reference this subnet | +| `name` | string | | | The Name of the subnet resource. | +| `natGatewayId` | string | `''` | | The resource ID of the NAT Gateway to use for the subnet | +| `networkSecurityGroupId` | string | `''` | | The resource ID of the network security group to assign to the subnet | +| `privateEndpointNetworkPolicies` | string | `''` | `[Disabled, Enabled, ]` | enable or disable apply network policies on private endpoint in the subnet. | +| `privateLinkServiceNetworkPolicies` | string | `''` | `[Disabled, Enabled, ]` | enable or disable apply network policies on private link service in the subnet. | +| `routeTableId` | string | `''` | | The resource ID of the route table to assign to the subnet | +| `serviceEndpointPolicies` | array | `[]` | | An array of service endpoint policies. | +| `serviceEndpoints` | array | `[]` | | The service endpoints to enable on the subnet | + + +### Parameter Usage: `delegations` + +```json +"delegations": [ + { + "name": "sqlMiDel", + "properties": { + "serviceName": "Microsoft.Sql/managedInstances" + } + } +] +``` + +### Parameter Usage: `serviceEndpoints` + +```json +"serviceEndpoints": [ + "Microsoft.EventHub", + "Microsoft.Sql", + "Microsoft.Storage", + "Microsoft.KeyVault" +] +``` + +## Considerations + +The `privateEndpointNetworkPolicies` property must be set to disabled for subnets that contain private endpoints. It confirms that NSGs rules will not apply to private endpoints (currently not supported, [reference](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-overview#limitations)). Default Value when not specified is "Enabled". + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network peering | +| `resourceGroupName` | string | The resource group the virtual network peering was deployed into | +| `resourceId` | string | The resource ID of the virtual network peering | +| `subnetAddressPrefix` | string | The address prefix for the subnet | +| `subnetAddressPrefixes` | array | List of address prefixes for the subnet | + +## Template references + +- [Virtualnetworks/Subnets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/subnets) diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/version.json b/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/subnets/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/carml/1.0.1/Microsoft.Network/virtualNetworks/version.json b/carml/1.0.1/Microsoft.Network/virtualNetworks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/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/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep new file mode 100644 index 000000000..8dfa90b89 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep @@ -0,0 +1,66 @@ +@description('Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName') +param name string = '${localVnetName}-${last(split(remoteVirtualNetworkId, '/'))}' + +@description('Required. The Name of the Virtual Network to add the peering to.') +param localVnetName string + +@description('Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID') +param remoteVirtualNetworkId string + +@description('Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true') +param allowForwardedTraffic bool = true + +@description('Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false') +param allowGatewayTransit bool = false + +@description('Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true') +param allowVirtualNetworkAccess bool = true + +@description('Optional. If we need to verify the provisioning state of the remote gateway. Default is true') +param doNotVerifyRemoteGateways bool = true + +@description('Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false') +param useRemoteGateways bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: localVnetName +} + +resource virtualNetworkPeering 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-05-01' = { + name: name + parent: virtualNetwork + properties: { + allowForwardedTraffic: allowForwardedTraffic + allowGatewayTransit: allowGatewayTransit + allowVirtualNetworkAccess: allowVirtualNetworkAccess + doNotVerifyRemoteGateways: doNotVerifyRemoteGateways + useRemoteGateways: useRemoteGateways + remoteVirtualNetwork: { + id: remoteVirtualNetworkId + } + } +} + +@description('The resource group the virtual network peering was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network peering') +output name string = virtualNetworkPeering.name + +@description('The resource ID of the virtual network peering') +output resourceId string = virtualNetworkPeering.id diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md b/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md new file mode 100644 index 000000000..46ac4e155 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md @@ -0,0 +1,55 @@ +# VirtualNetworkPeering `[Microsoft.Network/virtualNetworks/virtualNetworkPeerings]` + +This template deploys Virtual Network Peering. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | 2021-05-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- Local Virtual Network (Identified by the `localVnetName` parameter). +- Remote Virtual Network (Identified by the `remoteVirtualNetworkId` parameter) + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `localVnetName` | string | The Name of the Virtual Network to add the peering to. | +| `remoteVirtualNetworkId` | string | The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `allowForwardedTraffic` | bool | `True` | Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true | +| `allowGatewayTransit` | bool | `False` | If gateway links can be used in remote virtual networking to link to this virtual network. Default is false | +| `allowVirtualNetworkAccess` | bool | `True` | Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true | +| `doNotVerifyRemoteGateways` | bool | `True` | If we need to verify the provisioning state of the remote gateway. Default is true | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]` | The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName | +| `useRemoteGateways` | bool | `False` | If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network peering | +| `resourceGroupName` | string | The resource group the virtual network peering was deployed into | +| `resourceId` | string | The resource ID of the virtual network peering | + +## Template references + +- [Virtualnetworks/Virtualnetworkpeerings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/virtualNetworkPeerings) diff --git a/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/version.json b/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/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/carml/1.0.1/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..702e277f7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource virtualWan 'Microsoft.Network/virtualWans@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualWan.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualWan +}] diff --git a/carml/1.0.1/Microsoft.Network/virtualWans/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/virtualWans/.parameters/min.parameters.json new file mode 100644 index 000000000..badddffd7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualWans/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vw-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualWans/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/virtualWans/.parameters/parameters.json new file mode 100644 index 000000000..325af2525 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualWans/.parameters/parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vw-x-001" + }, + "type": { + "value": "Basic" + }, + "allowBranchToBranchTraffic": { + "value": true + }, + "allowVnetToVnetTraffic": { + "value": true + }, + "disableVpnEncryption": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/virtualWans/deploy.bicep b/carml/1.0.1/Microsoft.Network/virtualWans/deploy.bicep new file mode 100644 index 000000000..ed9577d22 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualWans/deploy.bicep @@ -0,0 +1,91 @@ +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Required. Name of the Virtual WAN.') +param name string + +@description('Optional. The type of the Virtual WAN.') +@allowed([ + 'Standard' + 'Basic' +]) +param type string = 'Standard' + +@description('Optional. True if branch to branch traffic is allowed.') +param allowBranchToBranchTraffic bool = false + +@description('Optional. True if VNET to VNET traffic is allowed. ') +param allowVnetToVnetTraffic bool = false + +@description('Optional. VPN encryption to be disabled or not.') +param disableVpnEncryption bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualWan 'Microsoft.Network/virtualWans@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + allowBranchToBranchTraffic: allowBranchToBranchTraffic + allowVnetToVnetTraffic: allowVnetToVnetTraffic ? allowVnetToVnetTraffic : null + disableVpnEncryption: disableVpnEncryption + type: type + } +} + +resource virtualWan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualWan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualWan +} + +module virtualWan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VWan-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualWan.id + } +}] + +@description('The name of the virtual WAN') +output name string = virtualWan.name + +@description('The resource ID of the virtual WAN') +output resourceId string = virtualWan.id + +@description('The resource group the virtual WAN was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/virtualWans/readme.md b/carml/1.0.1/Microsoft.Network/virtualWans/readme.md new file mode 100644 index 000000000..dc9b92914 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualWans/readme.md @@ -0,0 +1,96 @@ +# Virtual WANs `[Microsoft.Network/virtualWans]` + +This template deploys a virtual WAN. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/virtualWans` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Virtual WAN. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBranchToBranchTraffic` | bool | `False` | | True if branch to branch traffic is allowed. | +| `allowVnetToVnetTraffic` | bool | `False` | | True if VNET to VNET traffic is allowed. | +| `disableVpnEncryption` | bool | `False` | | VPN encryption to be disabled or not. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location where all resources will be created. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `type` | string | `'Standard'` | `[Standard, Basic]` | The type of the Virtual WAN. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual WAN | +| `resourceGroupName` | string | The resource group the virtual WAN was deployed into | +| `resourceId` | string | The resource ID of the virtual WAN | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualwans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualWans) diff --git a/carml/1.0.1/Microsoft.Network/virtualWans/version.json b/carml/1.0.1/Microsoft.Network/virtualWans/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/virtualWans/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/carml/1.0.1/Microsoft.Network/vpnGateways/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/vpnGateways/.parameters/min.parameters.json new file mode 100644 index 000000000..4ed3a736e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/.parameters/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": "<>-az-vpngw-min-001" + }, + "virtualHubResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/vpnGateways/.parameters/parameters.json new file mode 100644 index 000000000..af4f1eca8 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/.parameters/parameters.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vpngw-x-001" + }, + "virtualHubResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-x-001" + }, + "bgpSettings": { + "value": { + "asn": 65515, + "peerWeight": 0 + } + }, + "connections": { + "value": [ + { + "name": "Connection-<>-az-vsite-x-001", + "connectionBandwidth": 10, + "enableBgp": true, + "routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-x-001/hubRouteTables/defaultRouteTable" + }, + "propagatedRouteTables": { + "labels": [ + "default" + ], + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-x-001/hubRouteTables/defaultRouteTable" + } + ] + }, + "vnetRoutes": { + "staticRoutes": [] + } + }, + "remoteVpnSiteResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/vpnSites/<>-az-vsite-x-001" + } + ] + }, + "natRules": { + "value": [ + { + "name": "natRule1", + "internalMappings": [ + { + "addressSpace": "10.4.0.0/24" + } + ], + "externalMappings": [ + { + "addressSpace": "192.168.21.0/24" + } + ], + "type": "Static", + "mode": "EgressSnat" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/connections/deploy.bicep b/carml/1.0.1/Microsoft.Network/vpnGateways/connections/deploy.bicep new file mode 100644 index 000000000..6464b6440 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/connections/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. The name of the VPN connection.') +param name string + +@description('Required. The name of the VPN gateway this VPN connection is associated with.') +param vpnGatewayName string + +@description('Optional. The IPSec policies to be considered by this connection.') +param ipsecPolicies array = [] + +@description('Optional. The traffic selector policies to be considered by this connection.') +param trafficSelectorPolicies array = [] + +@description('Optional. List of all VPN site link connections to the gateway.') +param vpnLinkConnections array = [] + +@description('Optional. Routing configuration indicating the associated and propagated route tables for this connection.') +param routingConfiguration object = {} + +@description('Optional. Enable policy-based traffic selectors.') +param usePolicyBasedTrafficSelectors bool = false + +@description('Optional. Use local Azure IP to initiate connection.') +param useLocalAzureIpAddress bool = false + +@description('Optional. Enable rate limiting.') +param enableRateLimiting bool = false + +@description('Optional. Enable internet security.') +param enableInternetSecurity bool = false + +@description('Optional. Enable BGP flag.') +param enableBgp bool = false + +@description('Optional. Routing weight for VPN connection.') +param routingWeight int = 0 + +@description('Optional. Expected bandwidth in MBPS.') +param connectionBandwidth int = 10 + +@description('Optional. Gateway connection protocol.') +@allowed([ + 'IKEv1' + 'IKEv2' +]) +param vpnConnectionProtocolType string = 'IKEv2' + +@description('Optional. SharedKey for the VPN connection.') +param sharedKey string = '' + +@description('Optional. Reference to a VPN site to link to') +param remoteVpnSiteResourceId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-05-01' existing = { + name: vpnGatewayName +} + +resource vpnConnection 'Microsoft.Network/vpnGateways/vpnConnections@2021-05-01' = { + name: name + parent: vpnGateway + properties: { + connectionBandwidth: connectionBandwidth + enableBgp: enableBgp + enableInternetSecurity: enableInternetSecurity + enableRateLimiting: enableRateLimiting + ipsecPolicies: ipsecPolicies + remoteVpnSite: !empty(remoteVpnSiteResourceId) ? { + id: remoteVpnSiteResourceId + } : null + routingConfiguration: routingConfiguration + routingWeight: routingWeight + sharedKey: sharedKey + trafficSelectorPolicies: trafficSelectorPolicies + useLocalAzureIpAddress: useLocalAzureIpAddress + usePolicyBasedTrafficSelectors: usePolicyBasedTrafficSelectors + vpnConnectionProtocolType: vpnConnectionProtocolType + vpnLinkConnections: vpnLinkConnections + } +} + +@description('The name of the VPN connection') +output name string = vpnConnection.name + +@description('The resource ID of the VPN connection') +output resourceId string = vpnConnection.id + +@description('The name of the resource group the VPN connection was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/connections/readme.md b/carml/1.0.1/Microsoft.Network/vpnGateways/connections/readme.md new file mode 100644 index 000000000..364fa4930 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/connections/readme.md @@ -0,0 +1,79 @@ +# VPN Gateways Connections `[Microsoft.Network/vpnGateways/connections]` + +This module deploys VPN Gateways Connections. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/vpnGateways/vpnConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN connection. | +| `vpnGatewayName` | string | The name of the VPN gateway this VPN connection is associated with. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `connectionBandwidth` | int | `10` | | Expected bandwidth in MBPS. | +| `enableBgp` | bool | `False` | | Enable BGP flag. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableInternetSecurity` | bool | `False` | | Enable internet security. | +| `enableRateLimiting` | bool | `False` | | Enable rate limiting. | +| `ipsecPolicies` | array | `[]` | | The IPSec policies to be considered by this connection. | +| `remoteVpnSiteResourceId` | string | `''` | | Reference to a VPN site to link to | +| `routingConfiguration` | object | `{object}` | | Routing configuration indicating the associated and propagated route tables for this connection. | +| `routingWeight` | int | `0` | | Routing weight for VPN connection. | +| `sharedKey` | string | `''` | | SharedKey for the VPN connection. | +| `trafficSelectorPolicies` | array | `[]` | | The traffic selector policies to be considered by this connection. | +| `useLocalAzureIpAddress` | bool | `False` | | Use local Azure IP to initiate connection. | +| `usePolicyBasedTrafficSelectors` | bool | `False` | | Enable policy-based traffic selectors. | +| `vpnConnectionProtocolType` | string | `'IKEv2'` | `[IKEv1, IKEv2]` | Gateway connection protocol. | +| `vpnLinkConnections` | array | `[]` | | List of all VPN site link connections to the gateway. | + + +### Parameter Usage: `routingConfiguration` + +```json +"routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/SampleVirtualHub/hubRouteTables/defaultRouteTable" + }, + "propagatedRouteTables": { + "labels": [ + "default" + ], + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/SampleVirtualHub/hubRouteTables/defaultRouteTable" + } + ] + }, + "vnetRoutes": { + "staticRoutes": [] + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN connection | +| `resourceGroupName` | string | The name of the resource group the VPN connection was deployed into | +| `resourceId` | string | The resource ID of the VPN connection | + +## Template references + +- [Vpngateways/Vpnconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/vpnConnections) diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/connections/version.json b/carml/1.0.1/Microsoft.Network/vpnGateways/connections/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/connections/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/deploy.bicep b/carml/1.0.1/Microsoft.Network/vpnGateways/deploy.bicep new file mode 100644 index 000000000..3d39b2b31 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/deploy.bicep @@ -0,0 +1,117 @@ +@description('Required. Name of the VPN gateway') +param name string + +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Optional. The connections to create in the VPN gateway') +param connections array = [] + +@description('Optional. List of all the NAT Rules to associate with the gateway.') +param natRules array = [] + +@description('Required. The resource ID of a virtual Hub to connect to. Note: The virtual Hub and Gateway must be deployed into the same location.') +param virtualHubResourceId string + +@description('Optional. BGP settings details.') +param bgpSettings object = {} + +@description('Optional. Enable BGP routes translation for NAT on this VPN gateway.') +param enableBgpRouteTranslationForNat bool = false + +@description('Optional. Enable routing preference property for the public IP interface of the VPN gateway.') +param isRoutingPreferenceInternet bool = false + +@description('Optional. The scale unit for this VPN gateway.') +param vpnGatewayScaleUnit int = 2 + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + bgpSettings: bgpSettings + enableBgpRouteTranslationForNat: enableBgpRouteTranslationForNat + isRoutingPreferenceInternet: isRoutingPreferenceInternet + vpnGatewayScaleUnit: vpnGatewayScaleUnit + virtualHub: { + id: virtualHubResourceId + } + } +} + +resource vpnGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vpnGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vpnGateway +} + +module vpnGateway_natRules 'natRules/deploy.bicep' = [for (natRule, index) in natRules: { + name: '${deployment().name}-NATRule-${index}' + params: { + name: natRule.name + vpnGatewayName: vpnGateway.name + externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] + internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] + ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' + mode: contains(natRule, 'mode') ? natRule.mode : '' + type: contains(natRule, 'type') ? natRule.type : '' + } +}] + +module vpnGateway_connections 'connections/deploy.bicep' = [for (connection, index) in connections: { + name: '${deployment().name}-Connection-${index}' + params: { + name: connection.name + vpnGatewayName: vpnGateway.name + connectionBandwidth: contains(connection, 'connectionBandwidth') ? connection.connectionBandwidth : 10 + enableBgp: contains(connection, 'enableBgp') ? connection.enableBgp : false + enableInternetSecurity: contains(connection, 'enableInternetSecurity') ? connection.enableInternetSecurity : false + remoteVpnSiteResourceId: contains(connection, 'remoteVpnSiteResourceId') ? connection.remoteVpnSiteResourceId : '' + enableRateLimiting: contains(connection, 'enableRateLimiting') ? connection.enableRateLimiting : false + routingConfiguration: contains(connection, 'routingConfiguration') ? connection.routingConfiguration : {} + routingWeight: contains(connection, 'routingWeight') ? connection.routingWeight : 0 + sharedKey: contains(connection, 'sharedKey') ? connection.sharedKey : '' + useLocalAzureIpAddress: contains(connection, 'useLocalAzureIpAddress') ? connection.useLocalAzureIpAddress : false + usePolicyBasedTrafficSelectors: contains(connection, 'usePolicyBasedTrafficSelectors') ? connection.usePolicyBasedTrafficSelectors : false + vpnConnectionProtocolType: contains(connection, 'vpnConnectionProtocolType') ? connection.vpnConnectionProtocolType : 'IKEv2' + } +}] + +@description('The name of the VPN gateway') +output name string = vpnGateway.name + +@description('The resource ID of the VPN gateway') +output resourceId string = vpnGateway.id + +@description('The name of the resource group the VPN gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/deploy.bicep b/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/deploy.bicep new file mode 100644 index 000000000..05c117ae5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. The name of the NAT rule.') +param name string + +@description('Required. The name of the VPN gateway this NAT rule is associated with.') +param vpnGatewayName string + +@description('Optional. An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range.') +param externalMappings array = [] + +@description('Optional. An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range.') +param internalMappings array = [] + +@description('Optional. A NAT rule must be configured to a specific VPN Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both VPN Gateway instances.') +param ipConfigurationId string = '' + +@description('Optional. The type of NAT rule for VPN NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub\'s site-to-site VPN gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub\'s Site-to-site VPN gateway.') +@allowed([ + '' + 'EgressSnat' + 'IngressSnat' +]) +param mode string = '' + +@description('Optional. The type of NAT rule for VPN NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability.') +@allowed([ + '' + 'Dynamic' + 'Static' +]) +param type string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-05-01' existing = { + name: vpnGatewayName +} + +resource natRule 'Microsoft.Network/vpnGateways/natRules@2021-05-01' = { + name: name + parent: vpnGateway + properties: { + externalMappings: externalMappings + internalMappings: internalMappings + ipConfigurationId: !empty(ipConfigurationId) ? ipConfigurationId : null + mode: !empty(mode) ? any(mode) : null + type: !empty(type) ? any(type) : null + } +} + +@description('The name of the NAT rule') +output name string = natRule.name + +@description('The resource ID of the NAT rule') +output resourceId string = natRule.id + +@description('The name of the resource group the NAT rule was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/readme.md b/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/readme.md new file mode 100644 index 000000000..383a3b01a --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/readme.md @@ -0,0 +1,47 @@ +# VPN Gateways NATRules `[Microsoft.Network/vpnGateways/natRules]` + +This module deploys VPN Gateways NATRules + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/vpnGateways/natRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT rule. | +| `vpnGatewayName` | string | The name of the VPN gateway this NAT rule is associated with. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `externalMappings` | array | `[]` | | An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range. | +| `internalMappings` | array | `[]` | | An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range. | +| `ipConfigurationId` | string | `''` | | A NAT rule must be configured to a specific VPN Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both VPN Gateway instances. | +| `mode` | string | `''` | `[, EgressSnat, IngressSnat]` | The type of NAT rule for VPN NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub's site-to-site VPN gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub's Site-to-site VPN gateway. | +| `type` | string | `''` | `[, Dynamic, Static]` | The type of NAT rule for VPN NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT rule | +| `resourceGroupName` | string | The name of the resource group the NAT rule was deployed into | +| `resourceId` | string | The resource ID of the NAT rule | + +## Template references + +- [Vpngateways/Natrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/natRules) diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/version.json b/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/natRules/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/readme.md b/carml/1.0.1/Microsoft.Network/vpnGateways/readme.md new file mode 100644 index 000000000..02005d8a3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/readme.md @@ -0,0 +1,109 @@ +# VPN Gateways `[Microsoft.Network/vpnGateways]` + +This module deploys VPN Gateways. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/vpnGateways` | 2021-05-01 | +| `Microsoft.Network/vpnGateways/natRules` | 2021-05-01 | +| `Microsoft.Network/vpnGateways/vpnConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the VPN gateway | +| `virtualHubResourceId` | string | The resource ID of a virtual Hub to connect to. Note: The virtual Hub and Gateway must be deployed into the same location. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `bgpSettings` | object | `{object}` | | BGP settings details. | +| `connections` | _[connections](connections/readme.md)_ array | `[]` | | The connections to create in the VPN gateway | +| `enableBgpRouteTranslationForNat` | bool | `False` | | Enable BGP routes translation for NAT on this VPN gateway. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `isRoutingPreferenceInternet` | bool | `False` | | Enable routing preference property for the public IP interface of the VPN gateway. | +| `location` | string | `[resourceGroup().location]` | | Location where all resources will be created. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `natRules` | _[natRules](natRules/readme.md)_ array | `[]` | | List of all the NAT Rules to associate with the gateway. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `vpnGatewayScaleUnit` | int | `2` | | The scale unit for this VPN gateway. | + + +### Parameter Usage: + +### Parameter Usage: `bgpSettings` + +```json +"bgpSettings": { + "asn": 65515, + "peerWeight": 0, + "bgpPeeringAddresses": [ + { + "ipconfigurationId": "Instance0", + "defaultBgpIpAddresses": [ + "10.0.0.12" + ], + "customBgpIpAddresses": [], + "tunnelIpAddresses": [ + "20.84.35.53", + "10.0.0.4" + ] + }, + { + "ipconfigurationId": "Instance1", + "defaultBgpIpAddresses": [ + "10.0.0.13" + ], + "customBgpIpAddresses": [], + "tunnelIpAddresses": [ + "20.84.34.225", + "10.0.0.5" + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN gateway | +| `resourceGroupName` | string | The name of the resource group the VPN gateway was deployed into | +| `resourceId` | string | The resource ID of the VPN gateway | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Vpngateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways) +- [Vpngateways/Natrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/natRules) +- [Vpngateways/Vpnconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/vpnConnections) diff --git a/carml/1.0.1/Microsoft.Network/vpnGateways/version.json b/carml/1.0.1/Microsoft.Network/vpnGateways/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnGateways/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Network/vpnSites/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Network/vpnSites/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4452aae54 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnSites/.bicep/nested_rbac.bicep @@ -0,0 +1,37 @@ +param principalIds array +param principalType string = '' +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource vpnSite 'Microsoft.Network/vpnSites@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(vpnSite.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: vpnSite +}] diff --git a/carml/1.0.1/Microsoft.Network/vpnSites/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Network/vpnSites/.parameters/min.parameters.json new file mode 100644 index 000000000..24791e033 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnSites/.parameters/min.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vSite-min-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + }, + "ipAddress": { + "value": "1.2.3.4" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/apd-<>-az-vw-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/vpnSites/.parameters/parameters.json b/carml/1.0.1/Microsoft.Network/vpnSites/.parameters/parameters.json new file mode 100644 index 000000000..39ec5e30c --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnSites/.parameters/parameters.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vSite-x-001" + }, + "tags": { + "value": { + "tagA": "valueA", + "tagB": "valueB" + } + }, + "deviceProperties": { + "value": { + "linkSpeedInMbps": 0 + } + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/apd-<>-az-vw-x-001" + }, + "vpnSiteLinks": { + "value": [ + { + "name": "<>-az-vSite-x-001", + "properties": { + "bgpProperties": { + "asn": 65010, + "bgpPeeringAddress": "1.1.1.1" + }, + "ipAddress": "1.2.3.4", + "linkProperties": { + "linkProviderName": "contoso", + "linkSpeedInMbps": 5 + } + } + }, + { + "name": "Link1", + "properties": { + "bgpProperties": { + "asn": 65020, + "bgpPeeringAddress": "192.168.1.0" + }, + "ipAddress": "2.2.2.2", + "linkProperties": { + "linkProviderName": "contoso", + "linkSpeedInMbps": 5 + } + } + } + ] + }, + "o365Policy": { + "value": { + "breakOutCategories": { + "optimize": true, + "allow": true, + "default": true + } + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Network/vpnSites/deploy.bicep b/carml/1.0.1/Microsoft.Network/vpnSites/deploy.bicep new file mode 100644 index 000000000..1dd53818e --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnSites/deploy.bicep @@ -0,0 +1,105 @@ +@description('Required. Name of the VPN Site.') +param name string + +@description('Required. Resource ID of the virtual WAN to link to') +param virtualWanId string + +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. An array of IP address ranges that can be used by subnets of the virtual network. Must be provided if no bgpProperties or VPNSiteLinks are configured.') +param addressPrefixes array = [] + +@description('Optional. BGP settings details. Must be provided if no addressPrefixes or VPNSiteLinks are configured. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead.') +param bgpProperties object = {} + +@description('Optional. List of properties of the device.') +param deviceProperties object = {} + +@description('Optional. The IP-address for the VPN-site. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead.') +param ipAddress string = '' + +@description('Optional. IsSecuritySite flag') +param isSecuritySite bool = false + +@description('Optional. The Office365 breakout policy.') +param o365Policy object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. List of all VPN site links.') +param vpnSiteLinks array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnSite 'Microsoft.Network/vpnSites@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressSpace: !empty(addressPrefixes) ? { + addressPrefixes: addressPrefixes + } : null + bgpProperties: !empty(bgpProperties) ? bgpProperties : null + deviceProperties: !empty(deviceProperties) ? deviceProperties : null + ipAddress: !empty(ipAddress) ? ipAddress : null + isSecuritySite: isSecuritySite + o365Policy: !empty(o365Policy) ? o365Policy : null + virtualWan: { + id: virtualWanId + } + vpnSiteLinks: !empty(vpnSiteLinks) ? vpnSiteLinks : null + } +} + +resource vpnSite_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vpnSite.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vpnSite +} + +module vpnSite_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VWan-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: vpnSite.id + } +}] + +@description('The name of the VPN site') +output name string = vpnSite.name + +@description('The resource ID of the VPN site') +output resourceId string = vpnSite.id + +@description('The resource group the VPN site was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Network/vpnSites/readme.md b/carml/1.0.1/Microsoft.Network/vpnSites/readme.md new file mode 100644 index 000000000..7b7e9a1d3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnSites/readme.md @@ -0,0 +1,165 @@ +# VPN Sites `[Microsoft.Network/vpnSites]` + +This module deploys a VPN Site. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/vpnSites` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the VPN Site. | +| `virtualWanId` | string | Resource ID of the virtual WAN to link to | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefixes` | array | `[]` | | An array of IP address ranges that can be used by subnets of the virtual network. Must be provided if no bgpProperties or VPNSiteLinks are configured. | +| `bgpProperties` | object | `{object}` | | BGP settings details. Must be provided if no addressPrefixes or VPNSiteLinks are configured. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead. | +| `deviceProperties` | object | `{object}` | | List of properties of the device. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipAddress` | string | `''` | | The IP-address for the VPN-site. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead. | +| `isSecuritySite` | bool | `False` | | IsSecuritySite flag | +| `location` | string | `[resourceGroup().location]` | | Location where all resources will be created. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `o365Policy` | object | `{object}` | | The Office365 breakout policy. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `vpnSiteLinks` | array | `[]` | | List of all VPN site links. | + + +### Parameter Usage `o365Policy` + +```json +"o365Policy": { + "value": { + "breakOutCategories": { + "optimize": true, + "allow": true, + "default": true + } + } +} +``` + +### Parameter Usage `deviceProperties` + +```json +"deviceProperties": { + "value": { + "deviceModel": "morty", + "deviceVendor": "contoso", + "linkSpeedInMbps": 0 + } +} +``` + +### Parameter Usage `bgpProperties` + +The BGP properties. Note: This is a deprecated property, please use the corresponding `VpnSiteLinks` property instead. + +```json +"bgpProperties": { + "value": { + "asn": 65010, + "bgpPeeringAddress": "1.1.1.1", + "peerWeight": 0 + } +} +``` + +### Parameter Usage `vpnSiteLinks` + +An array of links. Should be used instead of the top-level `ipAddress` & `bgpProperties` properties. If using links, one default link with same name and properties as VpnSite itself is mandatory. + +```json +"vpnSiteLinks": { + "value": [ + { + "name": "<>-az-vSite-x-001", + "properties": { + "bgpProperties": { + "asn": 65010, + "bgpPeeringAddress": "1.1.1.1" + }, + "ipAddress": "1.2.3.4", + "linkProperties": { + "linkProviderName": "contoso", + "linkSpeedInMbps": 5 + } + } + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN site | +| `resourceGroupName` | string | The resource group the VPN site was deployed into | +| `resourceId` | string | The resource ID of the VPN site | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vpnsites](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnSites) diff --git a/carml/1.0.1/Microsoft.Network/vpnSites/version.json b/carml/1.0.1/Microsoft.Network/vpnSites/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Network/vpnSites/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c312d6691 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Azure Sentinel Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade') + 'Azure Sentinel Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb') + 'Azure Sentinel Responder': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Security Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd') + 'Security Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(logAnalyticsWorkspace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: logAnalyticsWorkspace +}] diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.bicep/nested_solutions.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.bicep/nested_solutions.bicep new file mode 100644 index 000000000..341438497 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.bicep/nested_solutions.bicep @@ -0,0 +1,32 @@ +param gallerySolution string +param logAnalyticsWorkspaceName string +param location string +param product string = 'OMSGallery' +param publisher string = 'Microsoft' + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource solution 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = { + name: '${gallerySolution}(${logAnalyticsWorkspace.name})' + location: location + properties: { + workspaceResourceId: logAnalyticsWorkspace.id + } + plan: { + name: '${gallerySolution}(${logAnalyticsWorkspace.name})' + product: '${product}/${gallerySolution}' + promotionCode: '' + publisher: publisher + } +} + +@description('The resource ID of the deployed solution') +output resourceId string = solution.id + +@description('The resource group where the solution will be deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed solution') +output name string = solution.name diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.parameters/min.parameters.json new file mode 100644 index 000000000..022048939 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-la-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.parameters/parameters.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..2f8d6d9b8 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/.parameters/parameters.json @@ -0,0 +1,168 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-la-x-001" + }, + "publicNetworkAccessForIngestion": { + "value": "Disabled" + }, + "publicNetworkAccessForQuery": { + "value": "Disabled" + }, + "dailyQuotaGb": { + "value": 10 + }, + "storageInsightsConfigs": { + "value": [ + { + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsalaw001", + "tables": [ + "WADWindowsEventLogsTable", + "WADETWEventTable", + "WADServiceFabric*EventTable", + "LinuxsyslogVer2v0" + ] + } + ] + }, + "linkedServices": { + "value": [ + { + "name": "Automation", + "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Automation/automationAccounts/adp-<>-wd-aut-x-001" + } + ] + }, + "savedSearches": { + "value": [ + { + "name": "VMSSQueries", + "displayName": "VMSS Instance Count2", + "category": "VDC Saved Searches", + "query": "Event | where Source == 'ServiceFabricNodeBootstrapAgent' | summarize AggregatedValue = count() by Computer" + } + ] + }, + "dataSources": { + "value": [ + { + "name": "applicationEvent", + "kind": "WindowsEvent", + "eventLogName": "Application", + "eventTypes": [ + { + "eventType": "Error" + }, + { + "eventType": "Warning" + }, + { + "eventType": "Information" + } + ] + }, + { + "name": "windowsPerfCounter1", + "kind": "WindowsPerformanceCounter", + "objectName": "Processor", + "instanceName": "*", + "intervalSeconds": 60, + "counterName": "% Processor Time" + }, + { + "name": "sampleIISLog1", + "kind": "IISLogs", + "state": "OnPremiseEnabled" + }, + { + "name": "sampleSyslog1", + "kind": "LinuxSyslog", + "syslogName": "kern", + "syslogSeverities": [ + { + "severity": "emerg" + }, + { + "severity": "alert" + }, + { + "severity": "crit" + }, + { + "severity": "err" + }, + { + "severity": "warning" + } + ] + }, + { + "name": "sampleSyslogCollection1", + "kind": "LinuxSyslogCollection", + "state": "Enabled" + }, + { + "name": "sampleLinuxPerf1", + "kind": "LinuxPerformanceObject", + "syslogSeverities": [ + { + "counterName": "% Used Inodes" + }, + { + "counterName": "Free Megabytes" + }, + { + "counterName": "% Used Space" + }, + { + "counterName": "Disk Transfers/sec" + }, + { + "counterName": "Disk Reads/sec" + }, + { + "counterName": "Disk Writes/sec" + } + ], + "objectName": "Logical Disk", + "instanceName": "*", + "intervalSeconds": 10 + }, + { + "name": "sampleLinuxPerfCollection1", + "kind": "LinuxPerformanceCollection", + "state": "Enabled" + } + ] + }, + "gallerySolutions": { + "value": [ + { + "name": "AzureAutomation", + "product": "OMSGallery", + "publisher": "Microsoft" + } + ] + }, + "useResourcePermissions": { + "value": true + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/deploy.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/deploy.bicep new file mode 100644 index 000000000..b977d4429 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. Name of the solution') +param name string + +@description('Required. The kind of the DataSource.') +@allowed([ + 'AzureActivityLog' + 'WindowsEvent' + 'WindowsPerformanceCounter' + 'IISLogs' + 'LinuxSyslog' + 'LinuxSyslogCollection' + 'LinuxPerformanceObject' + 'LinuxPerformanceCollection' +]) +param kind string = 'AzureActivityLog' + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +@description('Optional. Resource ID of the resource to be linked.') +param linkedResourceId string = '' + +@description('Optional. Windows event log name to configure when kind is WindowsEvent.') +param eventLogName string = '' + +@description('Optional. Windows event types to configure when kind is WindowsEvent.') +param eventTypes array = [] + +@description('Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') +param objectName string = '' + +@description('Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') +param instanceName string = '*' + +@description('Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject.') +param intervalSeconds int = 60 + +@description('Optional. List of counters to configure when the kind is LinuxPerformanceObject.') +param performanceCounters array = [] + +@description('Optional. Counter name to configure when kind is WindowsPerformanceCounter.') +param counterName string = '' + +@description('Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection.') +param state string = '' + +@description('Optional. System log to configure when kind is LinuxSyslog.') +param syslogName string = '' + +@description('Optional. Severities to configure when kind is LinuxSyslog.') +param syslogSeverities array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource dataSource 'Microsoft.OperationalInsights/workspaces/dataSources@2020-08-01' = { + name: name + parent: workspace + kind: kind + tags: tags + properties: { + linkedResourceId: !empty(kind) && kind == 'AzureActivityLog' ? linkedResourceId : null + eventLogName: !empty(kind) && kind == 'WindowsEvent' ? eventLogName : null + eventTypes: !empty(kind) && kind == 'WindowsEvent' ? eventTypes : null + objectName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? objectName : null + instanceName: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? instanceName : null + intervalSeconds: !empty(kind) && (kind == 'WindowsPerformanceCounter' || kind == 'LinuxPerformanceObject') ? intervalSeconds : null + counterName: !empty(kind) && kind == 'WindowsPerformanceCounter' ? counterName : null + state: !empty(kind) && (kind == 'IISLogs' || kind == 'LinuxSyslogCollection' || kind == 'LinuxPerformanceCollection') ? state : null + syslogName: !empty(kind) && kind == 'LinuxSyslog' ? syslogName : null + syslogSeverities: !empty(kind) && (kind == 'LinuxSyslog' || kind == 'LinuxPerformanceObject') ? syslogSeverities : null + performanceCounters: !empty(kind) && kind == 'LinuxPerformanceObject' ? performanceCounters : null + } +} + +@description('The resource ID of the deployed data source') +output resourceId string = dataSource.id + +@description('The resource group where the data source is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed data source') +output name string = dataSource.name diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/readme.md b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/readme.md new file mode 100644 index 000000000..64c3e1e43 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/readme.md @@ -0,0 +1,72 @@ +# Operationalinsights Workspaces Datasources `[Microsoft.OperationalInsights/workspaces/dataSources]` + +This template deploys a data source for a Log Analytics workspace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/dataSources` | 2020-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `kind` | string | `'AzureActivityLog'` | `[AzureActivityLog, WindowsEvent, WindowsPerformanceCounter, IISLogs, LinuxSyslog, LinuxSyslogCollection, LinuxPerformanceObject, LinuxPerformanceCollection]` | The kind of the DataSource. | +| `logAnalyticsWorkspaceName` | string | | | Name of the Log Analytics workspace | +| `name` | string | | | Name of the solution | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `counterName` | string | `''` | Counter name to configure when kind is WindowsPerformanceCounter. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `eventLogName` | string | `''` | Windows event log name to configure when kind is WindowsEvent. | +| `eventTypes` | array | `[]` | Windows event types to configure when kind is WindowsEvent. | +| `instanceName` | string | `'*'` | Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| `intervalSeconds` | int | `60` | Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| `linkedResourceId` | string | `''` | Resource ID of the resource to be linked. | +| `objectName` | string | `''` | Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject. | +| `performanceCounters` | array | `[]` | List of counters to configure when the kind is LinuxPerformanceObject. | +| `state` | string | `''` | State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection. | +| `syslogName` | string | `''` | System log to configure when kind is LinuxSyslog. | +| `syslogSeverities` | array | `[]` | Severities to configure when kind is LinuxSyslog. | +| `tags` | object | `{object}` | Tags to configure in the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed data source | +| `resourceGroupName` | string | The resource group where the data source is deployed | +| `resourceId` | string | The resource ID of the deployed data source | + +## Template references + +- [Workspaces/Datasources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/dataSources) diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/version.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/dataSources/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/carml/1.0.1/Microsoft.OperationalInsights/workspaces/deploy.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/deploy.bicep new file mode 100644 index 000000000..2b5da9f43 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/deploy.bicep @@ -0,0 +1,272 @@ +@description('Required. Name of the Log Analytics workspace') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Service Tier: PerGB2018, Free, Standalone, PerGB or PerNode') +@allowed([ + 'Free' + 'Standalone' + 'PerNode' + 'PerGB2018' +]) +param serviceTier string = 'PerGB2018' + +@description('Optional. List of storage accounts to be read by the workspace.') +param storageInsightsConfigs array = [] + +@description('Optional. List of services to be linked.') +param linkedServices array = [] + +@description('Optional. Kusto Query Language searches to save.') +param savedSearches array = [] + +@description('Optional. LAW data sources to configure.') +param dataSources array = [] + +@description('Optional. LAW gallerySolutions from the gallery.') +param gallerySolutions array = [] + +@description('Optional. Number of days data will be retained for') +@minValue(0) +@maxValue(730) +param dataRetention int = 365 + +@description('Optional. The workspace daily quota for ingestion.') +@minValue(-1) +param dailyQuotaGb int = -1 + +@description('Optional. The network access type for accessing Log Analytics ingestion.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Optional. The network access type for accessing Log Analytics query.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Optional. Set to \'true\' to use resource or workspace permissions and \'false\' (or leave empty) to require workspace permissions.') +param useResourcePermissions bool = false + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Audit' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Audit' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var logAnalyticsSearchVersion = 1 + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' = { + location: location + name: name + tags: tags + properties: { + features: { + searchVersion: logAnalyticsSearchVersion + enableLogAccessUsingOnlyResourcePermissions: useResourcePermissions + } + sku: { + name: serviceTier + } + retentionInDays: dataRetention + workspaceCapping: { + dailyQuotaGb: dailyQuotaGb + } + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + } +} + +resource logAnalyticsWorkspace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: logAnalyticsWorkspace +} + +module logAnalyticsWorkspace_storageInsightConfigs 'storageInsightConfigs/deploy.bicep' = [for (storageInsightsConfig, index) in storageInsightsConfigs: { + name: '${uniqueString(deployment().name, location)}-LAW-StorageInsightsConfig-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + containers: contains(storageInsightsConfig, 'containers') ? storageInsightsConfig.containers : [] + tables: contains(storageInsightsConfig, 'tables') ? storageInsightsConfig.tables : [] + storageAccountId: storageInsightsConfig.storageAccountId + } +}] + +module logAnalyticsWorkspace_linkedServices 'linkedServices/deploy.bicep' = [for (linkedService, index) in linkedServices: { + name: '${uniqueString(deployment().name, location)}-LAW-LinkedService-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: linkedService.name + resourceId: linkedService.resourceId + writeAccessResourceId: contains(linkedService, 'writeAccessResourceId') ? linkedService.writeAccessResourceId : '' + } +}] + +module logAnalyticsWorkspace_savedSearches 'savedSearches/deploy.bicep' = [for (savedSearch, index) in savedSearches: { + name: '${uniqueString(deployment().name, location)}-LAW-SavedSearch-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: '${savedSearch.name}${uniqueString(deployment().name)}' + displayName: savedSearch.displayName + category: savedSearch.category + query: savedSearch.query + functionAlias: contains(savedSearch, 'functionAlias') ? savedSearch.functionAlias : '' + functionParameters: contains(savedSearch, 'functionParameters') ? savedSearch.functionParameters : '' + version: contains(savedSearch, 'version') ? savedSearch.version : 2 + } +}] + +module logAnalyticsWorkspace_dataSources 'dataSources/deploy.bicep' = [for (dataSource, index) in dataSources: { + name: '${uniqueString(deployment().name, location)}-LAW-DataSource-${index}' + params: { + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + name: dataSource.name + kind: dataSource.kind + linkedResourceId: contains(dataSource, 'linkedResourceId') ? dataSource.linkedResourceId : '' + eventLogName: contains(dataSource, 'eventLogName') ? dataSource.eventLogName : '' + eventTypes: contains(dataSource, 'eventTypes') ? dataSource.eventTypes : [] + objectName: contains(dataSource, 'objectName') ? dataSource.objectName : '' + instanceName: contains(dataSource, 'instanceName') ? dataSource.instanceName : '' + intervalSeconds: contains(dataSource, 'intervalSeconds') ? dataSource.intervalSeconds : 60 + counterName: contains(dataSource, 'counterName') ? dataSource.counterName : '' + state: contains(dataSource, 'state') ? dataSource.state : '' + syslogName: contains(dataSource, 'syslogName') ? dataSource.syslogName : '' + syslogSeverities: contains(dataSource, 'syslogSeverities') ? dataSource.syslogSeverities : [] + performanceCounters: contains(dataSource, 'performanceCounters') ? dataSource.performanceCounters : [] + } +}] + +module logAnalyticsWorkspace_solutions '.bicep/nested_solutions.bicep' = [for (gallerySolution, index) in gallerySolutions: if (!empty(gallerySolutions)) { + name: '${uniqueString(deployment().name, location)}-LAW-Solution-${index}' + params: { + gallerySolution: gallerySolution.name + location: location + logAnalyticsWorkspaceName: logAnalyticsWorkspace.name + product: gallerySolution.product + publisher: gallerySolution.publisher + } +}] + +resource logAnalyticsWorkspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${logAnalyticsWorkspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: logAnalyticsWorkspace +} + +module logAnalyticsWorkspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LAW-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: logAnalyticsWorkspace.id + } +}] + +@description('The resource ID of the deployed log analytics workspace') +output resourceId string = logAnalyticsWorkspace.id + +@description('The resource group of the deployed log analytics workspace') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed log analytics workspace') +output name string = logAnalyticsWorkspace.name + +@description('The ID associated with the workspace') +output logAnalyticsWorkspaceId string = logAnalyticsWorkspace.properties.customerId diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/deploy.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/deploy.bicep new file mode 100644 index 000000000..257cc9ea5 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. Name of the link') +param name string + +@description('Required. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access.') +param resourceId string = '' + +@description('Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access. ') +param writeAccessResourceId string = '' + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource linkedService 'Microsoft.OperationalInsights/workspaces/linkedServices@2020-08-01' = { + name: name + parent: workspace + tags: tags + properties: { + resourceId: resourceId + writeAccessResourceId: empty(writeAccessResourceId) ? null : writeAccessResourceId + } +} + +@description('The resource ID of the deployed linked service') +output resourceId string = linkedService.id + +@description('The resource group where the linked service is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed linked service') +output name string = linkedService.name diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/readme.md b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/readme.md new file mode 100644 index 000000000..a02737e52 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/readme.md @@ -0,0 +1,62 @@ +# Operationalinsights Workspaces Linked Services `[Microsoft.OperationalInsights/workspaces/linkedServices]` + +This template deploys a linked service for a Log Analytics workspace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | 2020-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `logAnalyticsWorkspaceName` | string | | Name of the Log Analytics workspace | +| `name` | string | | Name of the link | +| `resourceId` | string | `''` | The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `tags` | object | `{object}` | Tags to configure in the resource. | +| `writeAccessResourceId` | string | `''` | The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed linked service | +| `resourceGroupName` | string | The resource group where the linked service is deployed | +| `resourceId` | string | The resource ID of the deployed linked service | + +## Template references + +- [Workspaces/Linkedservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedServices) diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/version.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/linkedServices/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/carml/1.0.1/Microsoft.OperationalInsights/workspaces/readme.md b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/readme.md new file mode 100644 index 000000000..1289495b9 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/readme.md @@ -0,0 +1,254 @@ +# Log Analytics Workspaces `[Microsoft.OperationalInsights/workspaces]` + +This template deploys a log analytics workspace. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.OperationalInsights/workspaces` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/dataSources` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/savedSearches` | 2020-08-01 | +| `Microsoft.OperationalInsights/workspaces/storageInsightConfigs` | 2020-08-01 | +| `Microsoft.OperationsManagement/solutions` | 2015-11-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Log Analytics workspace | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `dailyQuotaGb` | int | `-1` | | The workspace daily quota for ingestion. | +| `dataRetention` | int | `365` | | Number of days data will be retained for | +| `dataSources` | _[dataSources](dataSources/readme.md)_ array | `[]` | | LAW data sources to configure. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Audit]` | `[Audit]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `gallerySolutions` | array | `[]` | | LAW gallerySolutions from the gallery. | +| `linkedServices` | _[linkedServices](linkedServices/readme.md)_ array | `[]` | | List of services to be linked. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicNetworkAccessForIngestion` | string | `'Enabled'` | `[Enabled, Disabled]` | The network access type for accessing Log Analytics ingestion. | +| `publicNetworkAccessForQuery` | string | `'Enabled'` | `[Enabled, Disabled]` | The network access type for accessing Log Analytics query. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `savedSearches` | _[savedSearches](savedSearches/readme.md)_ array | `[]` | | Kusto Query Language searches to save. | +| `serviceTier` | string | `'PerGB2018'` | `[Free, Standalone, PerNode, PerGB2018]` | Service Tier: PerGB2018, Free, Standalone, PerGB or PerNode | +| `storageInsightsConfigs` | array | `[]` | | List of storage accounts to be read by the workspace. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `useResourcePermissions` | bool | `False` | | Set to 'true' to use resource or workspace permissions and 'false' (or leave empty) to require workspace permissions. | + + +### Parameter Usage: `gallerySolutions` + +```json +"gallerySolutions": { + + "value": [ + { + "name": "AgentHealthAssessment", + "product": "OMSGallery/AgentHealthAssessment", + "publisher": "Microsoft" + }, + { + "name": "AlertManagement", + "product": "OMSGallery/AlertManagement", + "publisher": "Microsoft" + }, + { + "name": "AntiMalware", + "product": "OMSGallery/AntiMalware", + "publisher": "Microsoft" + }, + { + "name": "AzureActivity", + "product": "OMSGallery/AzureActivity", + "publisher": "Microsoft" + }, + { + "name": "AzureAutomation", + "product": "OMSGallery/AzureAutomation", + "publisher": "Microsoft" + }, + { + "name": "AzureCdnCoreAnalytics", + "product": "OMSGallery/AzureCdnCoreAnalytics", + "publisher": "Microsoft" + }, + { + "name": "AzureDataFactoryAnalytics", + "product": "OMSGallery/AzureDataFactoryAnalytics", + "publisher": "Microsoft" + }, + { + "name": "AzureNSGAnalytics", + "product": "OMSGallery/AzureNSGAnalytics", + "publisher": "Microsoft" + }, + { + "name": "AzureSQLAnalytics", + "product": "OMSGallery/AzureSQLAnalytics", + "publisher": "Microsoft" + }, + { + "name": "ChangeTracking", + "product": "OMSGallery/ChangeTracking", + "publisher": "Microsoft" + }, + { + "name": "Containers", + "product": "OMSGallery/Containers", + "publisher": "Microsoft" + }, + { + "name": "InfrastructureInsights", + "product": "OMSGallery/InfrastructureInsights", + "publisher": "Microsoft" + }, + { + "name": "KeyVaultAnalytics", + "product": "OMSGallery/KeyVaultAnalytics", + "publisher": "Microsoft" + }, + { + "name": "LogicAppsManagement", + "product": "OMSGallery/LogicAppsManagement", + "publisher": "Microsoft" + }, + { + "name": "NetworkMonitoring", + "product": "OMSGallery/NetworkMonitoring", + "publisher": "Microsoft" + }, + { + "name": "Security", + "product": "OMSGallery/Security", + "publisher": "Microsoft" + }, + { + "name": "SecurityCenterFree", + "product": "OMSGallery/SecurityCenterFree", + "publisher": "Microsoft" + }, + { + "name": "ServiceFabric", + "product": "OMSGallery/ServiceFabric", + "publisher": "Microsoft" + }, + { + "name": "ServiceMap", + "product": "OMSGallery/ServiceMap", + "publisher": "Microsoft" + }, + { + "name": "SQLAssessment", + "product": "OMSGallery/SQLAssessment", + "publisher": "Microsoft" + }, + { + "name": "Updates", + "product": "OMSGallery/Updates", + "publisher": "Microsoft" + }, + { + "name": "VMInsights", + "product": "OMSGallery/VMInsights", + "publisher": "Microsoft" + }, + { + "name": "WireData2", + "product": "OMSGallery/WireData2", + "publisher": "Microsoft" + }, + { + "name": "WaaSUpdateInsights", + "product": "OMSGallery/WaaSUpdateInsights", + "publisher": "Microsoft" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `logAnalyticsWorkspaceId` | string | The ID associated with the workspace | +| `name` | string | The name of the deployed log analytics workspace | +| `resourceGroupName` | string | The resource group of the deployed log analytics workspace | +| `resourceId` | string | The resource ID of the deployed log analytics workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Solutions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces) +- [Workspaces/Datasources](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/dataSources) +- [Workspaces/Linkedservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedServices) +- [Workspaces/Savedsearches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/savedSearches) +- [Workspaces/Storageinsightconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/storageInsightConfigs) diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/deploy.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/deploy.bicep new file mode 100644 index 000000000..9c64f8246 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/deploy.bicep @@ -0,0 +1,68 @@ +@description('Required. Name of the Log Analytics workspace') +param logAnalyticsWorkspaceName string + +@description('Required. Name of the saved search') +param name string + +@description('Required. Display name for the search.') +param displayName string + +@description('Required. Query category.') +param category string + +@description('Required. Kusto Query to be stored.') +param query string + +@description('Optional. Tags to configure in the resource.') +param tags array = [] + +@description('Optional. The function alias if query serves as a function..') +param functionAlias string = '' + +@description('Optional. The optional function parameters if query serves as a function. Value should be in the following format: "param-name1:type1 = default_value1, param-name2:type2 = default_value2". For more examples and proper syntax please refer to /azure/kusto/query/functions/user-defined-functions.') +param functionParameters string = '' + +@description('Optional. The version number of the query language.') +param version int = 2 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource savedSearch 'Microsoft.OperationalInsights/workspaces/savedSearches@2020-08-01' = { + name: name + parent: workspace + properties: { + tags: tags + displayName: displayName + category: category + query: query + functionAlias: functionAlias + functionParameters: functionParameters + version: version + } +} + +@description('The resource ID of the deployed saved search') +output resourceId string = savedSearch.id + +@description('The resource group where the saved search is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed saved search') +output name string = savedSearch.name diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/readme.md b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/readme.md new file mode 100644 index 000000000..974c473c9 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/readme.md @@ -0,0 +1,66 @@ +# Operationalinsights Workspaces Saved Searches `[Microsoft.OperationalInsights/workspaces/savedSearches]` + +This template deploys a saved search for a Log Analytics workspace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/savedSearches` | 2020-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `category` | string | Query category. | +| `displayName` | string | Display name for the search. | +| `logAnalyticsWorkspaceName` | string | Name of the Log Analytics workspace | +| `name` | string | Name of the saved search | +| `query` | string | Kusto Query to be stored. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `functionAlias` | string | `''` | The function alias if query serves as a function.. | +| `functionParameters` | string | `''` | The optional function parameters if query serves as a function. Value should be in the following format: "param-name1:type1 = default_value1, param-name2:type2 = default_value2". For more examples and proper syntax please refer to /azure/kusto/query/functions/user-defined-functions. | +| `tags` | array | `[]` | Tags to configure in the resource. | +| `version` | int | `2` | The version number of the query language. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed saved search | +| `resourceGroupName` | string | The resource group where the saved search is deployed | +| `resourceId` | string | The resource ID of the deployed saved search | + +## Template references + +- [Workspaces/Savedsearches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/savedSearches) diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/version.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/savedSearches/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/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/deploy.bicep b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/deploy.bicep new file mode 100644 index 000000000..b86b20582 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/deploy.bicep @@ -0,0 +1,63 @@ +@description('Required. Name of the Log Analytics workspace.') +param logAnalyticsWorkspaceName string + +@description('Optional. The name of the storage insights config') +param name string = '${last(split(storageAccountId, '/'))}-stinsconfig' + +@description('Required. The Azure Resource Manager ID of the storage account resource.') +param storageAccountId string + +@description('Optional. The names of the blob containers that the workspace should read.') +param containers array = [] + +@description('Optional. The names of the Azure tables that the workspace should read.') +param tables array = [] + +@description('Optional. Tags to configure in the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: last(split(storageAccountId, '/')) +} + +resource workspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = { + name: logAnalyticsWorkspaceName +} + +resource storageinsightconfig 'Microsoft.OperationalInsights/workspaces/storageInsightConfigs@2020-08-01' = { + name: name + parent: workspace + tags: tags + properties: { + containers: containers + tables: tables + storageAccount: { + id: storageAccountId + key: storageAccount.listKeys().keys[0].value + } + } +} + +@description('The resource ID of the deployed storage insights configuration') +output resourceId string = storageinsightconfig.id + +@description('The resource group where the storage insight configuration is deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the storage insights configuration') +output name string = storageinsightconfig.name diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/readme.md b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/readme.md new file mode 100644 index 000000000..53d725a0c --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/readme.md @@ -0,0 +1,63 @@ +# Operationalinsights Workspaces Storage Insight Configs `[Microsoft.OperationalInsights/workspaces/storageInsightConfigs]` + +This template deploys a storage insights configuration for a Log Analytics workspace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.OperationalInsights/workspaces/storageInsightConfigs` | 2020-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `logAnalyticsWorkspaceName` | string | Name of the Log Analytics workspace. | +| `storageAccountId` | string | The Azure Resource Manager ID of the storage account resource. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `containers` | array | `[]` | The names of the blob containers that the workspace should read. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[format('{0}-stinsconfig', last(split(parameters('storageAccountId'), '/')))]` | The name of the storage insights config | +| `tables` | array | `[]` | The names of the Azure tables that the workspace should read. | +| `tags` | object | `{object}` | Tags to configure in the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the storage insights configuration | +| `resourceGroupName` | string | The resource group where the storage insight configuration is deployed | +| `resourceId` | string | The resource ID of the deployed storage insights configuration | + +## Template references + +- [Workspaces/Storageinsightconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/storageInsightConfigs) diff --git a/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/version.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/storageInsightConfigs/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/carml/1.0.1/Microsoft.OperationalInsights/workspaces/version.json b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.OperationalInsights/workspaces/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/carml/1.0.1/Microsoft.RecoveryServices/vaults/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d62f5cf3f --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(rsv.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: rsv +}] diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/dr.parameters.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/dr.parameters.json new file mode 100644 index 000000000..53bc61761 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/dr.parameters.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rsv-dr-001" + }, + "replicationFabrics": { + "value": [ + { + "location": "NorthEurope", + "replicationContainers": [ + { + "name": "ne-container1", + "replicationContainerMappings": [ + { + "targetProtectionContainerId": "/Subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.RecoveryServices/vaults/<>-az-rsv-min-001/replicationFabrics/NorthEurope/replicationProtectionContainers/ne-container2", + "policyName": "Default_values", + "targetContainerName": "pluto" + } + ] + }, + { + "name": "ne-container2", + "replicationContainerMappings": [ + { + "policyName": "Default_values", + "targetContainerFabricName": "WE-2", + "targetContainerName": "we-container1" + } + ] + } + ] + }, + { + "name": "WE-2", + "location": "WestEurope", + "replicationContainers": [ + { + "name": "we-container1", + "replicationContainerMappings": [ + { + "policyName": "Default_values", + "targetContainerFabricName": "NorthEurope", + "targetContainerName": "ne-container2" + } + ] + } + ] + } + ] + }, + "replicationPolicies": { + "value": [ + { + "name": "Default_values" + }, + { + "name": "Custom_values", + "appConsistentFrequencyInMinutes": 240, + "crashConsistentFrequencyInMinutes": 7, + "multiVmSyncStatus": "Disable", + "recoveryPointHistory": 2880 + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/min.parameters.json new file mode 100644 index 000000000..81ba350a3 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rsv-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/parameters.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/parameters.json new file mode 100644 index 000000000..dead4aa14 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/.parameters/parameters.json @@ -0,0 +1,286 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rsv-x-001" + }, + "backupConfig": { + "value": { + "enhancedSecurityState": "Disabled", + "softDeleteFeatureState": "Disabled" + } + }, + "backupPolicies": { + "value": [ + { + "name": "VMpolicy", + "properties": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 180, + "durationType": "Days" + } + }, + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + }, + "instantRpRetentionRangeInDays": 2, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + }, + { + "name": "sqlpolicy", + "properties": { + "backupManagementType": "AzureWorkload", + "workLoadType": "SQLDataBase", + "settings": { + "timeZone": "UTC", + "issqlcompression": true, + "isCompression": true + }, + "subProtectionPolicy": [ + { + "policyType": "Full", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Sunday" + ], + "scheduleRunTimes": [ + "2019-11-07T22:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 104, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + } + }, + { + "policyType": "Differential", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Monday" + ], + "scheduleRunTimes": [ + "2017-03-07T02:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + { + "policyType": "Log", + "schedulePolicy": { + "schedulePolicyType": "LogSchedulePolicy", + "scheduleFrequencyInMins": 120 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 15, + "durationType": "Days" + } + } + } + ], + "protectedItemsCount": 0 + } + }, + { + "name": "filesharepolicy", + "properties": { + "backupManagementType": "AzureStorage", + "workloadType": "AzureFileShare", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T04:30:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T04:30:00Z" + ], + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + } + ] + }, + "backupStorageConfig": { + "value": { + "storageModelType": "GeoRedundant", + "crossRegionRestoreFlag": true + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/deploy.bicep new file mode 100644 index 000000000..e8a4cb265 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/deploy.bicep @@ -0,0 +1,88 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Optional. Name of the Azure Recovery Service Vault Backup Policy') +param name string = 'vaultconfig' + +@description('Optional. Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param enhancedSecurityState string = 'Enabled' + +@description('Optional. ResourceGuard Operation Requests') +param resourceGuardOperationRequests array = [] + +@description('Optional. Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes') +@allowed([ + 'Disabled' + 'Enabled' +]) +param softDeleteFeatureState string = 'Enabled' + +@description('Optional. Storage type') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageModelType string = 'GeoRedundant' + +@description('Optional. Storage type') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageType string = 'GeoRedundant' + +@description('Optional. Once a machine is registered against a resource, the storageTypeState is always Locked.') +@allowed([ + 'Locked' + 'Unlocked' +]) +param storageTypeState string = 'Locked' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: recoveryVaultName +} + +resource backupConfig 'Microsoft.RecoveryServices/vaults/backupconfig@2021-10-01' = { + name: name + parent: rsv + properties: { + enhancedSecurityState: enhancedSecurityState + resourceGuardOperationRequests: resourceGuardOperationRequests + softDeleteFeatureState: softDeleteFeatureState + storageModelType: storageModelType + storageType: storageType + storageTypeState: storageTypeState + } +} + +@description('The name of the backup config') +output name string = backupConfig.name + +@description('The resource ID of the backup config') +output resourceId string = backupConfig.id + +@description('The name of the resource group the backup config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/readme.md new file mode 100644 index 000000000..be9f7633a --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/readme.md @@ -0,0 +1,48 @@ +# Recovery Services Vault Backup Config `[Microsoft.RecoveryServices/vaults/backupconfig]` + +This module deploys recovery services vault backup config. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupconfig` | 2021-10-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enhancedSecurityState` | string | `'Enabled'` | `[Disabled, Enabled]` | Enable this setting to protect hybrid backups against accidental deletes and add additional layer of authentication for critical operations. | +| `name` | string | `'vaultconfig'` | | Name of the Azure Recovery Service Vault Backup Policy | +| `resourceGuardOperationRequests` | array | `[]` | | ResourceGuard Operation Requests | +| `softDeleteFeatureState` | string | `'Enabled'` | `[Disabled, Enabled]` | Enable this setting to protect backup data for Azure VM, SQL Server in Azure VM and SAP HANA in Azure VM from accidental deletes | +| `storageModelType` | string | `'GeoRedundant'` | `[GeoRedundant, LocallyRedundant, ReadAccessGeoZoneRedundant, ZoneRedundant]` | Storage type | +| `storageType` | string | `'GeoRedundant'` | `[GeoRedundant, LocallyRedundant, ReadAccessGeoZoneRedundant, ZoneRedundant]` | Storage type | +| `storageTypeState` | string | `'Locked'` | `[Locked, Unlocked]` | Once a machine is registered against a resource, the storageTypeState is always Locked. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup config | +| `resourceGroupName` | string | The name of the resource group the backup config was created in. | +| `resourceId` | string | The resource ID of the backup config | + +## Template references + +- [Vaults/Backupconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-10-01/vaults/backupconfig) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupConfig/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/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/deploy.bicep new file mode 100644 index 000000000..6abbc8be3 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/deploy.bicep @@ -0,0 +1,42 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. Name of the Azure Recovery Service Vault Backup Policy') +param name string + +@description('Required. Configuration of the Azure Recovery Service Vault Backup Policy') +param backupPolicyProperties object + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: recoveryVaultName +} + +resource backupPolicy 'Microsoft.RecoveryServices/vaults/backupPolicies@2021-08-01' = { + name: name + parent: rsv + properties: backupPolicyProperties +} + +@description('The name of the backup policy') +output name string = backupPolicy.name + +@description('The resource ID of the backup policy') +output resourceId string = backupPolicy.id + +@description('The name of the resource group the backup policy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/readme.md new file mode 100644 index 000000000..31af6cdfd --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/readme.md @@ -0,0 +1,131 @@ +# RecoveryServicesVaultsBackupPolicies `[Microsoft.RecoveryServices/vaults/backupPolicies]` + +This module deploys a Backup Policy for a Recovery Services Vault + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupPolicies` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `backupPolicyProperties` | object | Configuration of the Azure Recovery Service Vault Backup Policy | +| `name` | string | Name of the Azure Recovery Service Vault Backup Policy | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +### Parameter Usage: `backupPolicyProperties` + +Object continaining the configuration for backup policies. It needs to be properly formatted and can be VM backup policies, SQL on VM backup policies or fileshare policies. The following example shows a VM backup policy. + +```json +"backupPolicyProperties": { + "value": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 180, + "durationType": "Days" + } + }, + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + }, + "instantRpRetentionRangeInDays": 2, + "timeZone": "UTC", + "protectedItemsCount": 0 + } +} +``` + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup policy | +| `resourceGroupName` | string | The name of the resource group the backup policy was created in. | +| `resourceId` | string | The resource ID of the backup policy | + +## Template references + +- [Vaults/Backuppolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupPolicies) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupPolicies/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/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/deploy.bicep new file mode 100644 index 000000000..5b8d42ef3 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/deploy.bicep @@ -0,0 +1,54 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Optional. The name of the backup storage config') +param name string = 'vaultstorageconfig' + +@description('Optional. Change Vault Storage Type (Works if vault has not registered any backup instance)') +@allowed([ + 'GeoRedundant' + 'LocallyRedundant' + 'ReadAccessGeoZoneRedundant' + 'ZoneRedundant' +]) +param storageModelType string = 'GeoRedundant' + +@description('Optional. Opt in details of Cross Region Restore feature') +param crossRegionRestoreFlag bool = true + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-12-01' existing = { + name: recoveryVaultName +} + +resource backupStorageConfig 'Microsoft.RecoveryServices/vaults/backupstorageconfig@2021-08-01' = { + name: name + parent: rsv + properties: { + storageModelType: storageModelType + crossRegionRestoreFlag: crossRegionRestoreFlag + } +} + +@description('The name of the backup storage config') +output name string = backupStorageConfig.name + +@description('The resource ID of the backup storage config') +output resourceId string = backupStorageConfig.id + +@description('The name of the Resource Group the backup storage configuration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md new file mode 100644 index 000000000..9ba5a8f97 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md @@ -0,0 +1,43 @@ +# RecoveryServicesVaultsBackupStorageConfig `[Microsoft.RecoveryServices/vaults/backupstorageconfig]` + +This module deploys the Backup Storage Configuration for the Recovery Service Vault +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupstorageconfig` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `crossRegionRestoreFlag` | bool | `True` | | Opt in details of Cross Region Restore feature | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'vaultstorageconfig'` | | The name of the backup storage config | +| `storageModelType` | string | `'GeoRedundant'` | `[GeoRedundant, LocallyRedundant, ReadAccessGeoZoneRedundant, ZoneRedundant]` | Change Vault Storage Type (Works if vault has not registered any backup instance) | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup storage config | +| `resourceGroupName` | string | The name of the Resource Group the backup storage configuration was created in. | +| `resourceId` | string | The resource ID of the backup storage config | + +## Template references + +- [Vaults/Backupstorageconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupstorageconfig) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/backupStorageConfig/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/carml/1.0.1/Microsoft.RecoveryServices/vaults/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/deploy.bicep new file mode 100644 index 000000000..555cde1ec --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/deploy.bicep @@ -0,0 +1,275 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param name string + +@description('Optional. The storage configuration for the Azure Recovery Service Vault') +param backupStorageConfig object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. List of all backup policies.') +param backupPolicies array = [] + +@description('Optional. The backup configuration.') +param backupConfig object = {} + +@description('Optional. List of all protection containers.') +@minLength(0) +param protectionContainers array = [] + +@description('Optional. List of all replication fabrics.') +@minLength(0) +param replicationFabrics array = [] + +@description('Optional. List of all replication policies.') +@minLength(0) +param replicationPolicies array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the Recovery Service Vault resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AzureBackupReport' + 'CoreAzureBackup' + 'AddonAzureBackupJobs' + 'AddonAzureBackupAlerts' + 'AddonAzureBackupPolicy' + 'AddonAzureBackupStorage' + 'AddonAzureBackupProtectedInstance' + 'AzureSiteRecoveryJobs' + 'AzureSiteRecoveryEvents' + 'AzureSiteRecoveryReplicatedItems' + 'AzureSiteRecoveryReplicationStats' + 'AzureSiteRecoveryRecoveryPoints' + 'AzureSiteRecoveryReplicationDataUploadRate' + 'AzureSiteRecoveryProtectedDiskDataChurn' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AzureBackupReport' + 'CoreAzureBackup' + 'AddonAzureBackupJobs' + 'AddonAzureBackupAlerts' + 'AddonAzureBackupPolicy' + 'AddonAzureBackupStorage' + 'AddonAzureBackupProtectedInstance' + 'AzureSiteRecoveryJobs' + 'AzureSiteRecoveryEvents' + 'AzureSiteRecoveryReplicatedItems' + 'AzureSiteRecoveryReplicationStats' + 'AzureSiteRecoveryRecoveryPoints' + 'AzureSiteRecoveryReplicationDataUploadRate' + 'AzureSiteRecoveryProtectedDiskDataChurn' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Health' +]) +param diagnosticMetricsToEnable array = [ + 'Health' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource rsv 'Microsoft.RecoveryServices/vaults@2021-11-01-preview' = { + name: name + location: location + tags: tags + identity: any(identity) + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: {} +} + +module rsv_replicationFabrics 'replicationFabrics/deploy.bicep' = [for (replicationFabric, index) in replicationFabrics: { + name: '${uniqueString(deployment().name, location)}-RSV-Fabric-${index}' + params: { + recoveryVaultName: rsv.name + name: contains(replicationFabric, 'name') ? replicationFabric.name : replicationFabric.location + location: replicationFabric.location + replicationContainers: contains(replicationFabric, 'replicationContainers') ? replicationFabric.replicationContainers : [] + } + dependsOn: [ + rsv_replicationPolicies + ] +}] + +module rsv_replicationPolicies 'replicationPolicies/deploy.bicep' = [for (replicationPolicy, index) in replicationPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-Policy-${index}' + params: { + name: replicationPolicy.name + recoveryVaultName: rsv.name + appConsistentFrequencyInMinutes: contains(replicationPolicy, 'appConsistentFrequencyInMinutes') ? replicationPolicy.appConsistentFrequencyInMinutes : 60 + crashConsistentFrequencyInMinutes: contains(replicationPolicy, 'crashConsistentFrequencyInMinutes') ? replicationPolicy.crashConsistentFrequencyInMinutes : 5 + multiVmSyncStatus: contains(replicationPolicy, 'multiVmSyncStatus') ? replicationPolicy.multiVmSyncStatus : 'Enable' + recoveryPointHistory: contains(replicationPolicy, 'recoveryPointHistory') ? replicationPolicy.recoveryPointHistory : 1440 + } +}] + +module rsv_backupStorageConfiguration 'backupStorageConfig/deploy.bicep' = if (!empty(backupStorageConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupStorageConfig' + params: { + recoveryVaultName: rsv.name + storageModelType: backupStorageConfig.storageModelType + crossRegionRestoreFlag: backupStorageConfig.crossRegionRestoreFlag + } +} + +module rsv_protectionContainers 'protectionContainers/deploy.bicep' = [for (protectionContainer, index) in protectionContainers: { + name: '${uniqueString(deployment().name, location)}-RSV-ProtectionContainers-${index}' + params: { + recoveryVaultName: rsv.name + name: protectionContainer.name + sourceResourceId: protectionContainer.sourceResourceId + friendlyName: protectionContainer.friendlyName + backupManagementType: protectionContainer.backupManagementType + containerType: protectionContainer.containerType + } +}] + +module rsv_backupPolicies 'backupPolicies/deploy.bicep' = [for (backupPolicy, index) in backupPolicies: { + name: '${uniqueString(deployment().name, location)}-RSV-BackupPolicy-${index}' + params: { + recoveryVaultName: rsv.name + name: backupPolicy.name + backupPolicyProperties: backupPolicy.properties + } +}] + +module rsv_backupConfig 'backupConfig/deploy.bicep' = if (!empty(backupConfig)) { + name: '${uniqueString(deployment().name, location)}-RSV-BackupConfig' + params: { + recoveryVaultName: rsv.name + name: contains(backupConfig, 'name') ? backupConfig.name : 'vaultconfig' + enhancedSecurityState: contains(backupConfig, 'enhancedSecurityState') ? backupConfig.enhancedSecurityState : 'Enabled' + resourceGuardOperationRequests: contains(backupConfig, 'resourceGuardOperationRequests') ? backupConfig.resourceGuardOperationRequests : [] + softDeleteFeatureState: contains(backupConfig, 'softDeleteFeatureState') ? backupConfig.softDeleteFeatureState : 'Enabled' + storageModelType: contains(backupConfig, 'storageModelType') ? backupConfig.storageModelType : 'GeoRedundant' + storageType: contains(backupConfig, 'storageType') ? backupConfig.storageType : 'GeoRedundant' + storageTypeState: contains(backupConfig, 'storageTypeState') ? backupConfig.storageTypeState : 'Locked' + } +} + +resource rsv_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${rsv.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: rsv +} + +resource rsv_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: rsv +} + +module rsv_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RSV-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: rsv.id + } +}] + +@description('The resource ID of the recovery services vault') +output resourceId string = rsv.id + +@description('The name of the resource group the recovery services vault was created in') +output resourceGroupName string = resourceGroup().name + +@description('The Name of the recovery services vault') +output name string = rsv.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(rsv.identity, 'principalId') ? rsv.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/deploy.bicep new file mode 100644 index 000000000..2264fe36f --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/deploy.bicep @@ -0,0 +1,75 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. Name of the Azure Recovery Service Vault Protection Container') +param name string + +@description('Optional. Backup management type to execute the current Protection Container job.') +@allowed([ + 'AzureBackupServer' + 'AzureIaasVM' + 'AzureSql' + 'AzureStorage' + 'AzureWorkload' + 'DPM' + 'DefaultBackup' + 'Invalid' + 'MAB' + '' +]) +param backupManagementType string = '' + +@description('Optional. Resource ID of the target resource for the Protection Container ') +param sourceResourceId string = '' + +@description('Optional. Friendly name of the Protection Container') +param friendlyName string = '' + +@description('Optional. Type of the container') +@allowed([ + 'AzureBackupServerContainer' + 'AzureSqlContainer' + 'GenericContainer' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'SQLAGWorkLoadContainer' + 'StorageContainer' + 'VMAppContainer' + 'Windows' + '' +]) +param containerType string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource protectionContainer 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers@2021-08-01' = { + name: '${recoveryVaultName}/Azure/${name}' + properties: { + sourceResourceId: !empty(sourceResourceId) ? sourceResourceId : null + friendlyName: !empty(friendlyName) ? friendlyName : null + backupManagementType: !empty(backupManagementType) ? backupManagementType : null + containerType: !empty(containerType) ? any(containerType) : null + } +} + +@description('The name of the Resource Group the Protection Container was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Protection Container.') +output resourceId string = protectionContainer.id + +@description('The Name of the Protection Container.') +output name string = protectionContainer.name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/readme.md new file mode 100644 index 000000000..a1778177d --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/readme.md @@ -0,0 +1,46 @@ +# RecoveryServicesProtectionContainer `[Microsoft.RecoveryServices/vaults/protectionContainers]` + +This module deploys a Protection Container for a Recovery Services Vault + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Recovery Service Vault Protection Container | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupManagementType` | string | `''` | `[AzureBackupServer, AzureIaasVM, AzureSql, AzureStorage, AzureWorkload, DPM, DefaultBackup, Invalid, MAB, ]` | Backup management type to execute the current Protection Container job. | +| `containerType` | string | `''` | `[AzureBackupServerContainer, AzureSqlContainer, GenericContainer, Microsoft.ClassicCompute/virtualMachines, Microsoft.Compute/virtualMachines, SQLAGWorkLoadContainer, StorageContainer, VMAppContainer, Windows, ]` | Type of the container | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `friendlyName` | string | `''` | | Friendly name of the Protection Container | +| `sourceResourceId` | string | `''` | | Resource ID of the target resource for the Protection Container | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the Protection Container. | +| `resourceGroupName` | string | The name of the Resource Group the Protection Container was created in. | +| `resourceId` | string | The resource ID of the Protection Container. | + +## Template references + +- [Vaults/Backupfabrics/Protectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupFabrics/protectionContainers) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/protectionContainers/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/carml/1.0.1/Microsoft.RecoveryServices/vaults/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/readme.md new file mode 100644 index 000000000..7f5a597f5 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/readme.md @@ -0,0 +1,445 @@ +# Recovery Services Vaults `[Microsoft.RecoveryServices/vaults]` + +This module deploys a recovery service vault. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.RecoveryServices/vaults` | 2021-11-01-preview | +| `Microsoft.RecoveryServices/vaults/backupconfig` | 2021-10-01 | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers` | 2021-08-01 | +| `Microsoft.RecoveryServices/vaults/backupPolicies` | 2021-08-01 | +| `Microsoft.RecoveryServices/vaults/backupstorageconfig` | 2021-08-01 | +| `Microsoft.RecoveryServices/vaults/replicationFabrics` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/replicationPolicies` | 2021-12-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupConfig` | _[backupConfig](backupConfig/readme.md)_ object | `{object}` | | The backup configuration. | +| `backupPolicies` | _[backupPolicies](backupPolicies/readme.md)_ array | `[]` | | List of all backup policies. | +| `backupStorageConfig` | _[backupStorageConfig](backupStorageConfig/readme.md)_ object | `{object}` | | The storage configuration for the Azure Recovery Service Vault | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[AzureBackupReport, CoreAzureBackup, AddonAzureBackupJobs, AddonAzureBackupAlerts, AddonAzureBackupPolicy, AddonAzureBackupStorage, AddonAzureBackupProtectedInstance, AzureSiteRecoveryJobs, AzureSiteRecoveryEvents, AzureSiteRecoveryReplicatedItems, AzureSiteRecoveryReplicationStats, AzureSiteRecoveryRecoveryPoints, AzureSiteRecoveryReplicationDataUploadRate, AzureSiteRecoveryProtectedDiskDataChurn]` | `[AzureBackupReport, CoreAzureBackup, AddonAzureBackupJobs, AddonAzureBackupAlerts, AddonAzureBackupPolicy, AddonAzureBackupStorage, AddonAzureBackupProtectedInstance, AzureSiteRecoveryJobs, AzureSiteRecoveryEvents, AzureSiteRecoveryReplicatedItems, AzureSiteRecoveryReplicationStats, AzureSiteRecoveryRecoveryPoints, AzureSiteRecoveryReplicationDataUploadRate, AzureSiteRecoveryProtectedDiskDataChurn]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Health]` | `[Health]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `protectionContainers` | _[protectionContainers](protectionContainers/readme.md)_ array | `[]` | | List of all protection containers. | +| `replicationFabrics` | _[replicationFabrics](replicationFabrics/readme.md)_ array | `[]` | | List of all replication fabrics. | +| `replicationPolicies` | _[replicationPolicies](replicationPolicies/readme.md)_ array | `[]` | | List of all replication policies. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the Recovery Service Vault resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `backupStorageConfig` + +```json +"backupStorageConfig": { + "value": { + "storageModelType": "GeoRedundant", + "crossRegionRestoreFlag": true + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `backupPolicies` + +Array of backup policies. They need to be properly formatted and can be VM backup policies, SQL on VM backup policies or fileshare policies. The following example shows all three types of backup policies. + +```json +"backupPolicies": { + "value": [ + { + "name": "VMpolicy", + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "properties": { + "backupManagementType": "AzureIaasVM", + "instantRPDetails": {}, + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T07:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 180, + "durationType": "Days" + } + }, + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 12, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T07:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + }, + "instantRpRetentionRangeInDays": 2, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + }, + { + "name": "sqlpolicy", + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "properties": { + "backupManagementType": "AzureWorkload", + "workLoadType": "SQLDataBase", + "settings": { + "timeZone": "UTC", + "issqlcompression": true, + "isCompression": true + }, + "subProtectionPolicy": [ + { + "policyType": "Full", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Sunday" + ], + "scheduleRunTimes": [ + "2019-11-07T22:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "weeklySchedule": { + "daysOfTheWeek": [ + "Sunday" + ], + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 104, + "durationType": "Weeks" + } + }, + "monthlySchedule": { + "retentionScheduleFormatType": "Weekly", + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 60, + "durationType": "Months" + } + }, + "yearlySchedule": { + "retentionScheduleFormatType": "Weekly", + "monthsOfYear": [ + "January" + ], + "retentionScheduleWeekly": { + "daysOfTheWeek": [ + "Sunday" + ], + "weeksOfTheMonth": [ + "First" + ] + }, + "retentionTimes": [ + "2019-11-07T22:00:00Z" + ], + "retentionDuration": { + "count": 10, + "durationType": "Years" + } + } + } + }, + { + "policyType": "Differential", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Weekly", + "scheduleRunDays": [ + "Monday" + ], + "scheduleRunTimes": [ + "2017-03-07T02:00:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + { + "policyType": "Log", + "schedulePolicy": { + "schedulePolicyType": "LogSchedulePolicy", + "scheduleFrequencyInMins": 120 + }, + "retentionPolicy": { + "retentionPolicyType": "SimpleRetentionPolicy", + "retentionDuration": { + "count": 15, + "durationType": "Days" + } + } + } + ], + "protectedItemsCount": 0 + } + }, + { + "name": "filesharepolicy", + "type": "Microsoft.RecoveryServices/vaults/backupPolicies", + "properties": { + "backupManagementType": "AzureStorage", + "workloadType": "AzureFileShare", + "schedulePolicy": { + "schedulePolicyType": "SimpleSchedulePolicy", + "scheduleRunFrequency": "Daily", + "scheduleRunTimes": [ + "2019-11-07T04:30:00Z" + ], + "scheduleWeeklyFrequency": 0 + }, + "retentionPolicy": { + "retentionPolicyType": "LongTermRetentionPolicy", + "dailySchedule": { + "retentionTimes": [ + "2019-11-07T04:30:00Z" + ], + "retentionDuration": { + "count": 30, + "durationType": "Days" + } + } + }, + "timeZone": "UTC", + "protectedItemsCount": 0 + } + } + ] +} +``` + +### Parameter Usage: `replicationFabrics` + +```json +"replicationFabrics": { + "value": [ + { + "location": "NorthEurope", + "replicationContainers": [ + { + "name": "ne-container1", + "replicationContainerMappings": [ + { + "policyName": "Default_values", + "targetContainerFabricName": "WestEurope-Fabric", + "targetContainerName": "we-conainer2" + } + ] + } + ] + }, + { + "name": "WestEurope-Fabric", //Optional + "location": "WestEurope", + "replicationContainers": [ + { + "name": "we-conainer2" + } + ] + } + ] +}, +``` + +### Parameter Usage: `replicationPolicies` + +```json +"replicationPolicies": { + "value": [ + { + "name": "Default_values" + }, + { + "name": "Custom_values", + "appConsistentFrequencyInMinutes": 240, + "crashConsistentFrequencyInMinutes": 7, + "multiVmSyncStatus": "Disable", + "recoveryPointHistory": 2880 + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The Name of the recovery services vault | +| `resourceGroupName` | string | The name of the resource group the recovery services vault was created in | +| `resourceId` | string | The resource ID of the recovery services vault | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-11-01-preview/vaults) +- [Vaults/Backupconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-10-01/vaults/backupconfig) +- [Vaults/Backupfabrics/Protectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupFabrics/protectionContainers) +- [Vaults/Backuppolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupPolicies) +- [Vaults/Backupstorageconfig](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-08-01/vaults/backupstorageconfig) +- [Vaults/Replicationfabrics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics) +- [Vaults/Replicationfabrics/Replicationprotectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers) +- [Vaults/Replicationfabrics/Replicationprotectioncontainers/Replicationprotectioncontainermappings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) +- [Vaults/Replicationpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationPolicies) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/deploy.bicep new file mode 100644 index 000000000..8e1ef4551 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/deploy.bicep @@ -0,0 +1,58 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. The recovery location the fabric represents') +param location string = resourceGroup().location + +@description('Optional. The name of the fabric') +param name string = location + +@description('Optional. Replication containers to create.') +param replicationContainers array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}-rsvPolicy' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource replicationFabric 'Microsoft.RecoveryServices/vaults/replicationFabrics@2021-12-01' = { + name: '${recoveryVaultName}/${name}' + properties: { + customDetails: { + instanceType: 'Azure' + location: location + } + } +} + +module fabric_replicationContainers 'replicationProtectionContainers/deploy.bicep' = [for (container, index) in replicationContainers: { + name: '${deployment().name}-RCont-${index}' + params: { + name: container.name + recoveryVaultName: recoveryVaultName + replicationFabricName: name + replicationContainerMappings: contains(container, 'replicationContainerMappings') ? container.replicationContainerMappings : [] + } + dependsOn: [ + replicationFabric + ] +}] + +@description('The name of the replication fabric.') +output name string = replicationFabric.name + +@description('The resource ID of the replication fabric.') +output resourceId string = replicationFabric.id + +@description('The name of the resource group the replication fabric was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/readme.md new file mode 100644 index 000000000..3358f53ba --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/readme.md @@ -0,0 +1,71 @@ +# RecoveryServices Vaults ReplicationFabrics `[Microsoft.RecoveryServices/vaults/replicationFabrics]` + +This module deploys a Replication Fabric for Azure to Azure disaster recovery scenario of Azure Site Recovery. + +> Note: this module currently support only the `instanceType: 'Azure'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationFabrics` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | 2021-12-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `location` | string | `[resourceGroup().location]` | The recovery location the fabric represents | +| `recoveryVaultName` | string | | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[parameters('location')]` | The name of the fabric | +| `replicationContainers` | array | `[]` | Replication containers to create. | + + +### Parameter Usage: `replicationContainers` + +```json +"replicationContainers": { + "value": [ + { + "name": "we-container1", + "replicationContainerMappings": [ //optional + { + "policyName": "Default_values", + "targetContainerName": "we-container2" + } + ] + }, + { + "name": "we-container2" + }, + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication fabric. | +| `resourceGroupName` | string | The name of the resource group the replication fabric was created in. | +| `resourceId` | string | The resource ID of the replication fabric. | + +## Template references + +- [Vaults/Replicationfabrics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics) +- [Vaults/Replicationfabrics/Replicationprotectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers) +- [Vaults/Replicationfabrics/Replicationprotectioncontainers/Replicationprotectioncontainermappings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/deploy.bicep new file mode 100644 index 000000000..a1d98c1b6 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/deploy.bicep @@ -0,0 +1,64 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. Name of the Replication Fabric') +param replicationFabricName string + +@description('Required. The name of the replication container') +param name string + +@description('Optional. Replication containers mappings to create.') +param replicationContainerMappings array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}-rsvPolicy' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource replicationContainer 'Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers@2021-12-01' = { + name: '${recoveryVaultName}/${replicationFabricName}/${name}' + properties: { + providerSpecificInput: [ + { + instanceType: 'A2A' + } + ] + } +} + +module fabric_container_containerMappings 'replicationProtectionContainerMappings/deploy.bicep' = [for (mapping, index) in replicationContainerMappings: { + name: '${deployment().name}-Map-${index}' + params: { + name: contains(mapping, 'name') ? mapping.name : '' + policyId: contains(mapping, 'policyId') ? mapping.policyId : '' + policyName: contains(mapping, 'policyName') ? mapping.policyName : '' + recoveryVaultName: recoveryVaultName + replicationFabricName: replicationFabricName + sourceProtectionContainerName: name + targetProtectionContainerId: contains(mapping, 'targetProtectionContainerId') ? mapping.targetProtectionContainerId : '' + targetContainerFabricName: contains(mapping, 'targetContainerFabricName') ? mapping.targetContainerFabricName : replicationFabricName + targetContainerName: contains(mapping, 'targetContainerName') ? mapping.targetContainerName : '' + } + dependsOn: [ + replicationContainer + ] +}] + +@description('The name of the replication container.') +output name string = replicationContainer.name + +@description('The resource ID of the replication container.') +output resourceId string = replicationContainer.id + +@description('The name of the resource group the replication container was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/readme.md new file mode 100644 index 000000000..e37c13275 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/readme.md @@ -0,0 +1,67 @@ +# RecoveryServices Vaults ReplicationFabrics ReplicationProtectionContainers `[Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers]` + +This module deploys a Replication Protection Container. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers` | 2021-12-01 | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | 2021-12-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication container | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | +| `replicationFabricName` | string | Name of the Replication Fabric | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `replicationContainerMappings` | array | `[]` | Replication containers mappings to create. | + + +### Parameter Usage: `replicationContainerMappings` + +```json +"replicationContainerMappings": { + "value": [ + { + "targetProtectionContainerId": "/Subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.RecoveryServices/vaults/<>-az-rsv-dr-001/replicationFabrics/NorthEurope/replicationProtectionContainers/ne-container1", + "policyId": "/Subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.RecoveryServices/vaults/<>-az-rsv-dr-001/replicationPolicies/Default_values" + }, + { + "name": null, //Optional + "policyName": "Default_values", + "targetContainerFabricName": "WestEurope", + "targetContainerName": "we-container" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication container. | +| `resourceGroupName` | string | The name of the resource group the replication container was created in. | +| `resourceId` | string | The resource ID of the replication container. | + +## Template references + +- [Vaults/Replicationfabrics/Replicationprotectioncontainers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers) +- [Vaults/Replicationfabrics/Replicationprotectioncontainers/Replicationprotectioncontainermappings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/deploy.bicep new file mode 100644 index 000000000..adfe75faf --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/deploy.bicep @@ -0,0 +1,65 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. Name of the Replication Fabric') +param replicationFabricName string + +@description('Required. Name of the source Replication container') +param sourceProtectionContainerName string + +@description('Optional. Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored') +param targetProtectionContainerId string = '' + +@description('Optional. Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored') +param targetContainerFabricName string = replicationFabricName + +@description('Optional. Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored') +param targetContainerName string = '' + +@description('Optional. Resource ID of the replication policy. If defined, policyName will be ignored') +param policyId string = '' + +@description('Optional. Name of the replication policy. Will be ignored if policyId is also specified') +param policyName string = '' + +@description('Optional. The name of the replication container mapping. If not provided, it will be automatically generated as `-`.') +param name string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var policyResourceId = policyId != '' ? policyId : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationPolicies', recoveryVaultName, policyName) +var targetProtectionContainerResourceId = targetProtectionContainerId != '' ? targetProtectionContainerId : subscriptionResourceId('Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers', recoveryVaultName, targetContainerFabricName, targetContainerName) +var mappingName = name != '' ? name : concat(sourceProtectionContainerName, '-', split(targetProtectionContainerResourceId, '/')[10]) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}-rsvPolicy' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource replicationContainer 'Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings@2021-12-01' = { + name: '${recoveryVaultName}/${replicationFabricName}/${sourceProtectionContainerName}/${mappingName}' + properties: { + targetProtectionContainerId: targetProtectionContainerResourceId + policyId: policyResourceId + providerSpecificInput: { + instanceType: 'A2A' + } + } +} + +@description('The name of the replication container.') +output name string = replicationContainer.name + +@description('The resource ID of the replication container.') +output resourceId string = replicationContainer.id + +@description('The name of the resource group the replication container was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/readme.md new file mode 100644 index 000000000..b02630439 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/readme.md @@ -0,0 +1,51 @@ +# RecoveryServices Vaults ReplicationFabrics ReplicationProtectionContainers ReplicationProtectionContainerMappings `[Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings]` + +This module deploys a Replication Protection Container Mapping. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings` | 2021-12-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | +| `replicationFabricName` | string | Name of the Replication Fabric | +| `sourceProtectionContainerName` | string | Name of the source Replication container | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `''` | The name of the replication container mapping. If not provided, it will be automatically generated as `-`. | +| `policyId` | string | `''` | Resource ID of the replication policy. If defined, policyName will be ignored | +| `policyName` | string | `''` | Name of the replication policy. Will be ignored if policyId is also specified | +| `targetContainerFabricName` | string | `[parameters('replicationFabricName')]` | Name of the fabric containing the target container. If targetProtectionContainerId is specified, this parameter will be ignored | +| `targetContainerName` | string | `''` | Name of the target container. Must be specified if targetProtectionContainerId is not. If targetProtectionContainerId is specified, this parameter will be ignored | +| `targetProtectionContainerId` | string | `''` | Resource ID of the target Replication container. Must be specified if targetContainerName is not. If specified, targetContainerFabricName and targetContainerName will be ignored | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication container. | +| `resourceGroupName` | string | The name of the resource group the replication container was created in. | +| `resourceId` | string | The resource ID of the replication container. | + +## Template references + +- [Vaults/Replicationfabrics/Replicationprotectioncontainers/Replicationprotectioncontainermappings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/replicationProtectionContainerMappings/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/replicationProtectionContainers/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationFabrics/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/deploy.bicep b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/deploy.bicep new file mode 100644 index 000000000..edb4d5b43 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/deploy.bicep @@ -0,0 +1,57 @@ +@description('Required. Name of the Azure Recovery Service Vault') +param recoveryVaultName string + +@description('Required. The name of the replication policy') +param name string + +@description('Optional. The app consistent snapshot frequency (in minutes).') +param appConsistentFrequencyInMinutes int = 60 + +@description('Optional. The crash consistent snapshot frequency (in minutes).') +param crashConsistentFrequencyInMinutes int = 5 + +@description('Optional. A value indicating whether multi-VM sync has to be enabled.') +@allowed([ + 'Enable' + 'Disable' +]) +param multiVmSyncStatus string = 'Enable' + +@description('Optional. The duration in minutes until which the recovery points need to be stored.') +param recoveryPointHistory int = 1440 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}-rsvPolicy' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource replicationPolicy 'Microsoft.RecoveryServices/vaults/replicationPolicies@2021-12-01' = { + name: '${recoveryVaultName}/${name}' + properties: { + providerSpecificInput: { + instanceType: 'A2A' + appConsistentFrequencyInMinutes: appConsistentFrequencyInMinutes + crashConsistentFrequencyInMinutes: crashConsistentFrequencyInMinutes + multiVmSyncStatus: multiVmSyncStatus + recoveryPointHistory: recoveryPointHistory + } + } +} +@description('The name of the replication policy.') +output name string = replicationPolicy.name + +@description('The resource ID of the replication policy.') +output resourceId string = replicationPolicy.id + +@description('The name of the resource group the replication policy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/readme.md b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/readme.md new file mode 100644 index 000000000..3a28a5572 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/readme.md @@ -0,0 +1,48 @@ +# RecoveryServices Vaults ReplicationPolicies `[Microsoft.RecoveryServices/vaults/replicationPolicies]` + +This module deploys a Replication Policy for Disaster Recovery scenario. + +> **Note**: this version of the module only supports the `instanceType: 'A2A'` scenario. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.RecoveryServices/vaults/replicationPolicies` | 2021-12-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication policy | +| `recoveryVaultName` | string | Name of the Azure Recovery Service Vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appConsistentFrequencyInMinutes` | int | `60` | | The app consistent snapshot frequency (in minutes). | +| `crashConsistentFrequencyInMinutes` | int | `5` | | The crash consistent snapshot frequency (in minutes). | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `multiVmSyncStatus` | string | `'Enable'` | `[Enable, Disable]` | A value indicating whether multi-VM sync has to be enabled. | +| `recoveryPointHistory` | int | `1440` | | The duration in minutes until which the recovery points need to be stored. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the replication policy. | +| `resourceGroupName` | string | The name of the resource group the replication policy was created in. | +| `resourceId` | string | The resource ID of the replication policy. | + +## Template references + +- [Vaults/Replicationpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-12-01/vaults/replicationPolicies) diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/replicationPolicies/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.RecoveryServices/vaults/version.json b/carml/1.0.1/Microsoft.RecoveryServices/vaults/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.RecoveryServices/vaults/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/carml/1.0.1/Microsoft.Resources/deploymentScripts/.parameters/cli.parameters.json b/carml/1.0.1/Microsoft.Resources/deploymentScripts/.parameters/cli.parameters.json new file mode 100644 index 000000000..e3e775a93 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/deploymentScripts/.parameters/cli.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": "<>-az-ds-cli-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "kind": { + "value": "AzureCLI" + }, + "azCliVersion": { + "value": "2.15.0" + }, + "scriptContent": { + "value": "echo \"Hello from inside the script\"" + }, + "retentionInterval": { + "value": "P1D" + }, + "runOnce": { + "value": false + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT30M" + } + } +} diff --git a/carml/1.0.1/Microsoft.Resources/deploymentScripts/.parameters/ps.parameters.json b/carml/1.0.1/Microsoft.Resources/deploymentScripts/.parameters/ps.parameters.json new file mode 100644 index 000000000..9f780f49a --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/deploymentScripts/.parameters/ps.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": "<>-az-ds-ps-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "kind": { + "value": "AzurePowerShell" + }, + "azPowerShellVersion": { + "value": "3.0" + }, + "scriptContent": { + "value": "Write-Host 'Running PowerShell from template'" + }, + "retentionInterval": { + "value": "P1D" + }, + "runOnce": { + "value": false + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT30M" + } + } +} diff --git a/carml/1.0.1/Microsoft.Resources/deploymentScripts/deploy.bicep b/carml/1.0.1/Microsoft.Resources/deploymentScripts/deploy.bicep new file mode 100644 index 000000000..65de5b3b0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/deploymentScripts/deploy.bicep @@ -0,0 +1,136 @@ +@description('Required. Display name of the script to be run.') +param name string + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Type of the script. AzurePowerShell, AzureCLI.') +@allowed([ + 'AzurePowerShell' + 'AzureCLI' +]) +param kind string = 'AzurePowerShell' + +@description('Optional. Azure PowerShell module version to be used.') +param azPowerShellVersion string = '3.0' + +@description('Optional. Azure CLI module version to be used.') +param azCliVersion string = '' + +@description('Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead.') +param scriptContent string = '' + +@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead.') +param primaryScriptUri string = '' + +@description('Optional. The environment variables to pass over to the script. Must have a \'name\' and a \'value\' or a \'secretValue\' property.') +param environmentVariables array = [] + +@description('Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent).') +param supportingScriptUris array = [] + +@description('Optional. Command-line arguments to pass to the script. Arguments are separated by spaces.') +param arguments string = '' + +@description('Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week).') +param retentionInterval string = 'P1D' + +@description('Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once.') +param runOnce bool = false + +@description('Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled).') +@allowed([ + 'Always' + 'OnSuccess' + 'OnExpiration' +]) +param cleanupPreference string = 'Always' + +@description('Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a \'containerGroupName\' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use \'containerGroupName\' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. \'containerGroupName\' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed.') +param containerGroupName string = '' + +@description('Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; \'PT30M\' - 30 minutes; \'P5D\' - 5 days; \'P1Y\' 1 year.') +param timeout string = 'PT1H' + +@description('Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var containerSettings = { + containerGroupName: containerGroupName +} + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: name + location: location + tags: tags + identity: identity + kind: any(kind) + properties: { + azPowerShellVersion: kind == 'AzurePowerShell' ? azPowerShellVersion : null + azCliVersion: kind == 'AzureCLI' ? azCliVersion : null + containerSettings: empty(containerGroupName) ? null : containerSettings + arguments: arguments + environmentVariables: empty(environmentVariables) ? null : environmentVariables + scriptContent: empty(scriptContent) ? null : scriptContent + primaryScriptUri: empty(primaryScriptUri) ? null : primaryScriptUri + supportingScriptUris: empty(supportingScriptUris) ? null : supportingScriptUris + cleanupPreference: cleanupPreference + forceUpdateTag: runOnce ? resourceGroup().name : baseTime + retentionInterval: retentionInterval + timeout: timeout + } +} + +resource deploymentScript_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${deploymentScript.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: deploymentScript +} + +@description('The resource ID of the deployment script') +output resourceId string = deploymentScript.id + +@description('The resource group the deployment script was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployment script') +output name string = deploymentScript.name diff --git a/carml/1.0.1/Microsoft.Resources/deploymentScripts/readme.md b/carml/1.0.1/Microsoft.Resources/deploymentScripts/readme.md new file mode 100644 index 000000000..a82e6c9dc --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/deploymentScripts/readme.md @@ -0,0 +1,100 @@ +# Deployment Scripts `[Microsoft.Resources/deploymentScripts]` + +This module deploys a deployment script. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Resources/deploymentScripts` | 2020-10-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Display name of the script to be run. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `arguments` | string | `''` | | Command-line arguments to pass to the script. Arguments are separated by spaces. | +| `azCliVersion` | string | `''` | | Azure CLI module version to be used. | +| `azPowerShellVersion` | string | `'3.0'` | | Azure PowerShell module version to be used. | +| `cleanupPreference` | string | `'Always'` | `[Always, OnSuccess, OnExpiration]` | The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled). | +| `containerGroupName` | string | `''` | | Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `environmentVariables` | array | `[]` | | The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property. | +| `kind` | string | `'AzurePowerShell'` | `[AzurePowerShell, AzureCLI]` | Type of the script. AzurePowerShell, AzureCLI. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `primaryScriptUri` | string | `''` | | Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead. | +| `retentionInterval` | string | `'P1D'` | | Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week). | +| `runOnce` | bool | `False` | | When set to false, script will run every time the template is deployed. When set to true, the script will only run once. | +| `scriptContent` | string | `''` | | Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead. | +| `supportingScriptUris` | array | `[]` | | List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent). | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeout` | string | `'PT1H'` | | Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('yyyy-MM-dd-HH-mm-ss')]` | Do not provide a value! This date value is used to make sure the script run every time the template is deployed. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployment script | +| `resourceGroupName` | string | The resource group the deployment script was deployed into | +| `resourceId` | string | The resource ID of the deployment script | + +## Considerations + +This module requires a User Assigned Identity (MSI, managed service identity) to exist, and this MSI has to have contributor rights on the subscription - that allows the Deployment Script to create the required Storage Account and the Azure Container Instance. + +## Template references + +- [Deploymentscripts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2020-10-01/deploymentScripts) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.0.1/Microsoft.Resources/deploymentScripts/version.json b/carml/1.0.1/Microsoft.Resources/deploymentScripts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/deploymentScripts/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/carml/1.0.1/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep b/carml/1.0.1/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep new file mode 100644 index 000000000..c3f891565 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep @@ -0,0 +1,31 @@ +@description('Optional. The name of the Lock') +param name string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Set lock level.') +param level string = 'NotSpecified' + +var lockNotes = { + CanNotDelete: 'Cannot delete resource or child resources.' + ReadOnly: 'Cannot modify the resource or child resources.' +} + +var lockName = empty(name) ? '${level}-lock' : name + +resource lock 'Microsoft.Authorization/locks@2017-04-01' = if (level != 'NotSpecified') { + name: lockName + properties: { + level: level + notes: lockNotes[level] + } +} + +@description('The resource ID of the lock') +output resourceId string = lock.id + +@description('The name of the lock') +output name string = lock.name diff --git a/carml/1.0.1/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..0fe91115a --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,208 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'AcrDelete': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11') + 'AcrImageSigner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'AcrPush': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec') + 'AcrQuarantineReader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04') + 'AcrQuarantineWriter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608') + 'API Management Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c') + 'API Management Service Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61') + 'API Management Service Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d') + 'App Configuration Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b') + 'App Configuration Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Application Insights Snapshot Debugger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b') + 'Attestation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e') + 'Attestation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3') + 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') + 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') + 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Azure Connected Machine Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7') + 'Azure Connected Machine Resource Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302') + 'Azure Digital Twins Owner (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe') + 'Azure Digital Twins Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8') + 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f') + 'Azure Kubernetes Service Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8') + 'Azure Maps Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204') + 'Azure Maps Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa') + 'Azure Sentinel Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade') + 'Azure Sentinel Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb') + 'Azure Sentinel Responder': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Azure Stack Registration Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Billing Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64') + 'BizTalk Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342') + 'Blockchain Member Node Access (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24') + 'Blueprint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4') + 'Blueprint Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090') + 'CDN Endpoint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45') + 'CDN Endpoint Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd') + 'CDN Profile Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432') + 'CDN Profile Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af') + 'Classic Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f') + 'Classic Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25') + 'Classic Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d') + 'Classic Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb') + 'ClearDB MySQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe') + 'Cognitive Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68') + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3') + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f') + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c') + 'Cognitive Services Custom Vision Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73') + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b') + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c') + 'Cognitive Services QnA Maker Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025') + 'Cognitive Services QnA Maker Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126') + 'Cognitive Services User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Cosmos DB Account Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'CosmosBackupOperator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb') + 'Cost Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430') + 'Cost Management Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3') + 'Data Box Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5') + 'Data Box Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027') + 'Data Factory Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5') + 'Data Lake Analytics Developer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Desktop Virtualization User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'Experimentation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c') + 'Experimentation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c') + 'Experimentation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1') + 'FHIR Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd') + 'FHIR Data Exporter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843') + 'FHIR Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508') + 'FHIR Data Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913') + 'Graph Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9') + 'HDInsight Cluster Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a') + 'HDInsight Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c') + 'Hierarchy Settings Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d') + 'Hybrid Server Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb') + 'Hybrid Server Resource Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624') + 'Integration Service Environment Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8') + 'Integration Service Environment Developer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec') + 'Intelligent Systems Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Knowledge Consumer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c') + 'Kubernetes Cluster - Azure Arc Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41') + 'Lab Creator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Managed Services Registration assignment Delete ': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46') + 'Management Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c') + 'Management Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d') + 'Marketplace Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'New Relic APM Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237') + 'Object Understanding Account Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745') + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Policy Insights Data Writer (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Redis Cache Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17') + 'Remote Rendering Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e') + 'Remote Rendering Client': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Scheduler Job Collections Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94') + 'Search Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0') + 'Security Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd') + 'Security Assessment Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5') + 'Security Manager (Legacy)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10') + 'Security Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4') + 'SignalR AccessKey Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e') + 'SignalR Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') + 'Spatial Anchors Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827') + 'Spatial Anchors Account Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c') + 'Spatial Anchors Account Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413') + 'SQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'SQL Server Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Support Request Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e') + 'Tag Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f') + 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + 'Workbook Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad') + 'Workbook Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d') +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(last(split(resourceId, '/')), principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } +}] diff --git a/carml/1.0.1/Microsoft.Resources/resourceGroups/.parameters/parameters.json b/carml/1.0.1/Microsoft.Resources/resourceGroups/.parameters/parameters.json new file mode 100644 index 000000000..3be494132 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/resourceGroups/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rg-x-001" + }, + "tags": { + "value": { + "Test": "Yes" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Resources/resourceGroups/deploy.bicep b/carml/1.0.1/Microsoft.Resources/resourceGroups/deploy.bicep new file mode 100644 index 000000000..f14994442 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/resourceGroups/deploy.bicep @@ -0,0 +1,71 @@ +targetScope = 'subscription' + +@description('Required. The name of the Resource Group') +param name string + +@description('Optional. Location of the Resource Group. It uses the deployment\'s location when not provided.') +param location string = deployment().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the storage account resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2019-05-01' = { + location: location + name: name + tags: tags + properties: {} +} + +module resourceGroup_lock '.bicep/nested_lock.bicep' = if (lock != 'NotSpecified') { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-RG-${lock}-Lock' + params: { + name: '${resourceGroup.name}-${lock}-lock' + level: lock + } +} + +module resourceGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RG-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: resourceGroup.id + } + scope: resourceGroup +}] + +@description('The name of the resource group') +output name string = resourceGroup.name + +@description('The resource ID of the resource group') +output resourceId string = resourceGroup.id diff --git a/carml/1.0.1/Microsoft.Resources/resourceGroups/readme.md b/carml/1.0.1/Microsoft.Resources/resourceGroups/readme.md new file mode 100644 index 000000000..f6059b713 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/resourceGroups/readme.md @@ -0,0 +1,96 @@ +# Resource Groups `[Microsoft.Resources/resourceGroups]` + +This module deploys a resource group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Considerations](#Considerations) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Resources/resourceGroups` | 2019-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Resource Group | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location of the Resource Group. It uses the deployment's location when not provided. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the storage account resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Considerations + +This module requires a User Assigned Identity (MSI, managed service identity) to exist, and this MSI has to have contributor rights on the subscription - that allows the Deployment Script to create the required Storage Account and the Azure Container Instance. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the resource group | +| `resourceId` | string | The resource ID of the resource group | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Resourcegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-05-01/resourceGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Resources/resourceGroups/version.json b/carml/1.0.1/Microsoft.Resources/resourceGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/resourceGroups/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/carml/1.0.1/Microsoft.Resources/tags/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Resources/tags/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.1/Microsoft.Resources/tags/.parameters/rg.parameters.json b/carml/1.0.1/Microsoft.Resources/tags/.parameters/rg.parameters.json new file mode 100644 index 000000000..a90e2e5b2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/.parameters/rg.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "onlyUpdate": { + "value": false + }, + "tags": { + "value": { + "Test": "Yes", + "TestToo": "No" + } + }, + "resourceGroupName": { + "value": "validation-rg" + } + } +} diff --git a/carml/1.0.1/Microsoft.Resources/tags/.parameters/sub.parameters.json b/carml/1.0.1/Microsoft.Resources/tags/.parameters/sub.parameters.json new file mode 100644 index 000000000..840b23ba6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/.parameters/sub.parameters.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "onlyUpdate": { + "value": true + }, + "tags": { + "value": { + "Test": "Yes", + "TestToo": "No" + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Resources/tags/deploy.bicep b/carml/1.0.1/Microsoft.Resources/tags/deploy.bicep new file mode 100644 index 000000000..ddb50937b --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/deploy.bicep @@ -0,0 +1,56 @@ +targetScope = 'subscription' + +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@description('Optional. Name of the Resource Group to assign the tags to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription.') +param resourceGroupName string = '' + +@description('Optional. Subscription ID of the subscription to assign the tags to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription.') +param subscriptionId string = subscription().id + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module tags_sub 'subscriptions/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${deployment().name}-Tags-Sub' + params: { + onlyUpdate: onlyUpdate + tags: tags + location: location + } +} + +module tags_rg 'resourceGroups/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${deployment().name}-Tags-RG' + scope: resourceGroup(resourceGroupName) + params: { + onlyUpdate: onlyUpdate + tags: tags + } +} + +@description('The name of the tags resource') +output name string = (!empty(resourceGroupName) && !empty(subscriptionId)) ? tags_rg.outputs.name : tags_sub.outputs.name + +@description('The applied tags') +output tags object = (!empty(resourceGroupName) && !empty(subscriptionId)) ? tags_rg.outputs.tags : tags_sub.outputs.tags diff --git a/carml/1.0.1/Microsoft.Resources/tags/readme.md b/carml/1.0.1/Microsoft.Resources/tags/readme.md new file mode 100644 index 000000000..b5665a5eb --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/readme.md @@ -0,0 +1,57 @@ +# Resources Tags `[Microsoft.Resources/tags]` + +This module deploys Resources Tags on a subscription or resource group scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `onlyUpdate` | bool | `False` | Instead of overwriting the existing tags, combine them with the new tags | +| `resourceGroupName` | string | `''` | Name of the Resource Group to assign the tags to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription. | +| `subscriptionId` | string | `[subscription().id]` | Subscription ID of the subscription to assign the tags to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription. | +| `tags` | object | `{object}` | Tags for the resource group. If not provided, removes existing tags | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep new file mode 100644 index 000000000..0f3301f97 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep @@ -0,0 +1,9 @@ +@description('Optional. The name of the tags resource.') +param name string = 'default' + +resource tags 'Microsoft.Resources/tags@2019-10-01' existing = { + name: name +} + +@description('Tags currently applied to the subscription level') +output existingTags object = contains(tags.properties, 'tags') ? tags.properties.tags : {} diff --git a/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/deploy.bicep b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/deploy.bicep new file mode 100644 index 000000000..81993a0cd --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/deploy.bicep @@ -0,0 +1,48 @@ +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module readTags '.bicep/readTags.bicep' = if (onlyUpdate) { + name: '${deployment().name}-ReadTags' +} + +var newTags = (onlyUpdate) ? union(readTags.outputs.existingTags, tags) : tags + +resource tag 'Microsoft.Resources/tags@2019-10-01' = { + name: name + properties: { + tags: newTags + } +} + +@description('The name of the tags resource') +output name string = tag.name + +@description('The resourceId of the resource group the tags were applied to') +output resourceId string = resourceGroup().id + +@description('The name of the resource group the tags were applied to') +output resourceGroupName string = resourceGroup().name + +@description('The applied tags') +output tags object = newTags diff --git a/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/readme.md b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/readme.md new file mode 100644 index 000000000..43279ae11 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/readme.md @@ -0,0 +1,57 @@ +# Resources Tags ResourceGroups `[Microsoft.Resources/tags/resourceGroups]` + +This module deploys Resources Tags on a resource group scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the tags resource. | +| `onlyUpdate` | bool | `False` | Instead of overwriting the existing tags, combine them with the new tags | +| `tags` | object | `{object}` | Tags for the resource group. If not provided, removes existing tags | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `resourceGroupName` | string | The name of the resource group the tags were applied to | +| `resourceId` | string | The resourceId of the resource group the tags were applied to | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/version.json b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/resourceGroups/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep new file mode 100644 index 000000000..65b245725 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep @@ -0,0 +1,11 @@ +targetScope = 'subscription' + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +resource tags 'Microsoft.Resources/tags@2019-10-01' existing = { + name: name +} + +@description('Tags currently applied to the subscription level') +output existingTags object = contains(tags.properties, 'tags') ? tags.properties.tags : {} diff --git a/carml/1.0.1/Microsoft.Resources/tags/subscriptions/deploy.bicep b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/deploy.bicep new file mode 100644 index 000000000..7424c11bc --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/deploy.bicep @@ -0,0 +1,48 @@ +targetScope = 'subscription' + +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module readTags '.bicep/readTags.bicep' = if (onlyUpdate) { + name: '${deployment().name}-ReadTags' +} + +var newTags = (onlyUpdate) ? union(readTags.outputs.existingTags, tags) : tags + +resource tag 'Microsoft.Resources/tags@2019-10-01' = { + name: name + properties: { + tags: newTags + } +} + +@description('The name of the tags resource') +output name string = tag.name + +@description('The applied tags') +output tags object = newTags diff --git a/carml/1.0.1/Microsoft.Resources/tags/subscriptions/readme.md b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/readme.md new file mode 100644 index 000000000..38fb51f39 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/readme.md @@ -0,0 +1,56 @@ +# Resources Tags Subscriptions `[Microsoft.Resources/tags/subscriptions]` + +This module deploys Resources Tags on a subscription scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `name` | string | `'default'` | The name of the tags resource. | +| `onlyUpdate` | bool | `False` | Instead of overwriting the existing tags, combine them with the new tags | +| `tags` | object | `{object}` | Tags for the resource group. If not provided, removes existing tags | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.0.1/Microsoft.Resources/tags/subscriptions/version.json b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/subscriptions/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Resources/tags/version.json b/carml/1.0.1/Microsoft.Resources/tags/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Resources/tags/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/Microsoft.Security/azureSecurityCenter/.bicep/nested_iotSecuritySolutions.bicep b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/.bicep/nested_iotSecuritySolutions.bicep new file mode 100644 index 000000000..5f37462ee --- /dev/null +++ b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/.bicep/nested_iotSecuritySolutions.bicep @@ -0,0 +1,16 @@ +@description('Optional. Security Solution data') +param ioTSecuritySolutionProperties object = {} + +resource iotSecuritySolutions 'Microsoft.Security/iotSecuritySolutions@2019-08-01' = if (!empty(ioTSecuritySolutionProperties)) { + name: 'iotSecuritySolutions' + properties: { + workspace: ioTSecuritySolutionProperties.workspace + displayName: ioTSecuritySolutionProperties.displayName + status: ioTSecuritySolutionProperties.status + export: ioTSecuritySolutionProperties.export + disabledDataSources: ioTSecuritySolutionProperties.disabledDataSources + iotHubs: ioTSecuritySolutionProperties.iotHubs + userDefinedResources: ioTSecuritySolutionProperties.userDefinedResources + recommendationsConfiguration: ioTSecuritySolutionProperties.recommendationsConfiguration + } +} diff --git a/carml/1.0.1/Microsoft.Security/azureSecurityCenter/.parameters/parameters.json b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/.parameters/parameters.json new file mode 100644 index 000000000..cfa02a1dd --- /dev/null +++ b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/.parameters/parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "scope": { + "value": "/subscriptions/<>" + }, + "securityContactProperties": { + "value": { + "email": "foo@contoso.com", + "phone": "+12345678", + "alertNotifications": "Off", + "alertsToAdmins": "Off" + } + }, + "workspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Security/azureSecurityCenter/deploy.bicep b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/deploy.bicep new file mode 100644 index 000000000..70b2980a2 --- /dev/null +++ b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/deploy.bicep @@ -0,0 +1,273 @@ +targetScope = 'subscription' + +@description('Required. The full Azure ID of the workspace to save the data in.') +param workspaceId string + +@description('Required. All the VMs in this scope will send their security data to the mentioned workspace unless overridden by a setting with more specific scope.') +param scope string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Describes what kind of security agent provisioning action to take. - On or Off') +@allowed([ + 'On' + 'Off' +]) +param autoProvision string = 'On' + +@description('Optional. Device Security group data') +param deviceSecurityGroupProperties object = {} + +@description('Optional. Security Solution data') +param ioTSecuritySolutionProperties object = {} + +@description('Optional. The pricing tier value for VMs. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param virtualMachinesPricingTier string = 'Free' + +@description('Optional. The pricing tier value for SqlServers. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param sqlServersPricingTier string = 'Free' + +@description('Optional. The pricing tier value for AppServices. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param appServicesPricingTier string = 'Free' + +@description('Optional. The pricing tier value for StorageAccounts. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param storageAccountsPricingTier string = 'Free' + +@description('Optional. The pricing tier value for SqlServerVirtualMachines. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param sqlServerVirtualMachinesPricingTier string = 'Free' + +@description('Optional. The pricing tier value for KubernetesService. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param kubernetesServicePricingTier string = 'Free' + +@description('Optional. The pricing tier value for ContainerRegistry. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param containerRegistryPricingTier string = 'Free' + +@description('Optional. The pricing tier value for KeyVaults. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param keyVaultsPricingTier string = 'Free' + +@description('Optional. The pricing tier value for DNS. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param dnsPricingTier string = 'Free' + +@description('Optional. The pricing tier value for ARM. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param armPricingTier string = 'Free' + +@description('Optional. The pricing tier value for OpenSourceRelationalDatabases. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param openSourceRelationalDatabasesTier string = 'Free' + +@description('Optional. The pricing tier value for containers. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param containersTier string = 'Free' + +@description('Optional. The pricing tier value for CosmosDbs. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard') +@allowed([ + 'Free' + 'Standard' +]) +param cosmosDbsTier string = 'Free' + +@description('Optional. Security contact data') +param securityContactProperties object = {} + +@description('Optional. Location deployment metadata.') +param location string = deployment().location + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource autoProvisioningSettings 'Microsoft.Security/autoProvisioningSettings@2017-08-01-preview' = { + name: 'default' + properties: { + autoProvision: autoProvision + } +} + +resource deviceSecurityGroups 'Microsoft.Security/deviceSecurityGroups@2019-08-01' = if (!empty(deviceSecurityGroupProperties)) { + name: 'deviceSecurityGroups' + properties: { + thresholdRules: deviceSecurityGroupProperties.thresholdRules + timeWindowRules: deviceSecurityGroupProperties.timeWindowRules + allowlistRules: deviceSecurityGroupProperties.allowlistRules + denylistRules: deviceSecurityGroupProperties.denylistRules + } +} + +module iotSecuritySolutions '.bicep/nested_iotSecuritySolutions.bicep' = if (!empty(ioTSecuritySolutionProperties)) { + name: '${uniqueString(deployment().name)}-ASC-IotSecuritySolutions' + scope: resourceGroup(empty(ioTSecuritySolutionProperties) ? 'dummy' : ioTSecuritySolutionProperties.resourceGroup) + params: { + ioTSecuritySolutionProperties: ioTSecuritySolutionProperties + } +} + +resource VirtualMachinesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'VirtualMachines' + properties: { + pricingTier: virtualMachinesPricingTier + } +} + +resource SqlServersPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'SqlServers' + properties: { + pricingTier: sqlServersPricingTier + } +} + +resource AppServicesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'AppServices' + properties: { + pricingTier: appServicesPricingTier + } +} + +resource StorageAccountsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'StorageAccounts' + properties: { + pricingTier: storageAccountsPricingTier + } +} + +resource SqlServerVirtualMachinesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'SqlServerVirtualMachines' + properties: { + pricingTier: sqlServerVirtualMachinesPricingTier + } +} + +resource KubernetesServicePricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'KubernetesService' + properties: { + pricingTier: kubernetesServicePricingTier + } +} + +resource ContainerRegistryPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'ContainerRegistry' + properties: { + pricingTier: containerRegistryPricingTier + } +} + +resource KeyVaultsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'KeyVaults' + properties: { + pricingTier: keyVaultsPricingTier + } +} + +resource DnsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'Dns' + properties: { + pricingTier: dnsPricingTier + } +} + +resource ArmPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'Arm' + properties: { + pricingTier: armPricingTier + } +} + +resource OpenSourceRelationalDatabasesPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'OpenSourceRelationalDatabases' + properties: { + pricingTier: openSourceRelationalDatabasesTier + } +} + +resource ContainersPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'Containers' + properties: { + pricingTier: containersTier + } +} + +resource CosmosDbsPricingTier 'Microsoft.Security/pricings@2018-06-01' = { + name: 'CosmosDbs' + properties: { + pricingTier: cosmosDbsTier + } +} + +resource securityContacts 'Microsoft.Security/securityContacts@2017-08-01-preview' = if (!empty(securityContactProperties)) { + name: 'securityContacts' + properties: { + email: securityContactProperties.email + phone: securityContactProperties.phone + alertNotifications: securityContactProperties.alertNotifications + alertsToAdmins: securityContactProperties.alertsToAdmins + } +} + +resource workspaceSettings 'Microsoft.Security/workspaceSettings@2017-08-01-preview' = { + name: 'default' + properties: { + workspaceId: workspaceId + scope: scope + } + dependsOn: [ + autoProvisioningSettings + ] +} + +@description('The resource IDs of the used log analytics workspace') +output workspaceId string = workspaceId diff --git a/carml/1.0.1/Microsoft.Security/azureSecurityCenter/readme.md b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/readme.md new file mode 100644 index 000000000..12275392a --- /dev/null +++ b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/readme.md @@ -0,0 +1,159 @@ +# Azure Security Center `[Microsoft.Security/azureSecurityCenter]` + +This template enables Azure security center - Standard tier by default, could be overridden. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Security/autoProvisioningSettings` | 2017-08-01-preview | +| `Microsoft.Security/deviceSecurityGroups` | 2019-08-01 | +| `Microsoft.Security/iotSecuritySolutions` | 2019-08-01 | +| `Microsoft.Security/pricings` | 2018-06-01 | +| `Microsoft.Security/securityContacts` | 2017-08-01-preview | +| `Microsoft.Security/workspaceSettings` | 2017-08-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `scope` | string | All the VMs in this scope will send their security data to the mentioned workspace unless overridden by a setting with more specific scope. | +| `workspaceId` | string | The full Azure ID of the workspace to save the data in. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appServicesPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for AppServices. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `armPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for ARM. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `autoProvision` | string | `'On'` | `[On, Off]` | Describes what kind of security agent provisioning action to take. - On or Off | +| `containerRegistryPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for ContainerRegistry. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `containersTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for containers. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `cosmosDbsTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for CosmosDbs. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `deviceSecurityGroupProperties` | object | `{object}` | | Device Security group data | +| `dnsPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for DNS. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ioTSecuritySolutionProperties` | object | `{object}` | | Security Solution data | +| `keyVaultsPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for KeyVaults. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `kubernetesServicePricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for KubernetesService. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `openSourceRelationalDatabasesTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for OpenSourceRelationalDatabases. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `securityContactProperties` | object | `{object}` | | Security contact data | +| `sqlServersPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for SqlServers. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `sqlServerVirtualMachinesPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for SqlServerVirtualMachines. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `storageAccountsPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for StorageAccounts. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | +| `virtualMachinesPricingTier` | string | `'Free'` | `[Free, Standard]` | The pricing tier value for VMs. Azure Security Center is provided in two pricing tiers: free and standard, with the standard tier available with a trial period. The standard tier offers advanced security capabilities, while the free tier offers basic security features. - Free or Standard | + + +### Parameter Usage: `deviceSecurityGroupProperties` + +```json +"deviceSecurityGroupProperties": { + "value": { + "thresholdRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "minThreshold": "integer", + "maxThreshold": "integer" + } + ], + "timeWindowRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "minThreshold": "integer", + "maxThreshold": "integer", + "timeWindowSize": "string" + } + ], + "allowlistRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "allowlistValues": [ + "string" + ] + } + ], + "denylistRules": [ + { + "isEnabled": "boolean", + "ruleType": "string", + "denylistValues": [ + "string" + ] + } + ] + } +} +``` + +### Parameter Usage: `ioTSecuritySolutionProperties` + +```json +"ioTSecuritySolutionProperties": { + "value": { + "resourceGroup": "string", + "workspace": "string", + "displayName": "string", + "status": "string", + "export": [ + "RawEvents" + ], + "disabledDataSources": [ + "TwinData" + ], + "iotHubs": [ + "string" + ], + "userDefinedResources": { + "query": "string", + "querySubscriptions": [ + "string" + ] + }, + "recommendationsConfiguration": [ + { + "recommendationType": "string", + "status": "string" + } + ] + } +} +``` + +### Parameter Usage: `securityContactProperties` + +```json +"securityContactProperties": { + "value": { + "email": "test@contoso.com", + "phone": "+12345678", + "alertNotifications": "On", + "alertsToAdmins": "Off" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `workspaceId` | string | The resource IDs of the used log analytics workspace | + +## Template references + +- [Autoprovisioningsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2017-08-01-preview/autoProvisioningSettings) +- [Devicesecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2019-08-01/deviceSecurityGroups) +- [Iotsecuritysolutions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2019-08-01/iotSecuritySolutions) +- [Pricings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2018-06-01/pricings) +- [Securitycontacts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2017-08-01-preview/securityContacts) +- [Workspacesettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Security/2017-08-01-preview/workspaceSettings) diff --git a/carml/1.0.1/Microsoft.Security/azureSecurityCenter/version.json b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/version.json new file mode 100644 index 000000000..badc0a228 --- /dev/null +++ b/carml/1.0.1/Microsoft.Security/azureSecurityCenter/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.5" +} diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/.bicep/nested_privateEndpoints.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.bicep/nested_privateEndpoints.bicep new file mode 100644 index 000000000..d1381aa57 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.bicep/nested_privateEndpoints.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpoint object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpoint, 'name') ? (empty(privateEndpoint.name) ? '${privateEndpointResourceName}-${privateEndpoint.service}' : privateEndpoint.name) : '${privateEndpointResourceName}-${privateEndpoint.service}' + subnetResourceId: privateEndpoint.subnetResourceId + service: [ + privateEndpoint.service + ] + privateDnsZoneResourceIds: contains(privateEndpoint, 'privateDnsZoneResourceIds') ? (empty(privateEndpoint.privateDnsZoneResourceIds) ? [] : privateEndpoint.privateDnsZoneResourceIds) : [] + customDnsConfigs: contains(privateEndpoint, 'customDnsConfigs') ? (empty(privateEndpoint.customDnsConfigs) ? null : privateEndpoint.customDnsConfigs) : null +} + +resource privateEndpoint_name 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateEndpoint_name_default 'privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: 'default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + } +} diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d48ad030c --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(namespace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: namespace +}] diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/.parameters/parameters.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.parameters/parameters.json new file mode 100644 index 000000000..6a1694eee --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/.parameters/parameters.json @@ -0,0 +1,156 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sbn-x-002" + }, + "skuName": { + "value": "Premium" + }, + "tags": { + "value": {} + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "disasterRecoveryConfigs": { + "value": {} + }, + "migrationConfigurations": { + "value": {} + }, + "virtualNetworkRules": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-003" + ] + }, + "ipFilterRules": { + "value": [ + { + "filterName": "ipFilter1", + "ipMask": "10.0.1.0/32", + "action": "Accept" + }, + { + "filterName": "ipFilter2", + "ipMask": "10.0.2.0/32", + "action": "Accept" + } + ] + }, + "authorizationRules": { + "value": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + }, + "queues": { + "value": [ + { + "name": "<>-az-sbq-x-002", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "authorizationRules": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + } + ] + }, + "topics": { + "value": [ + { + "name": "<>-az-sbt-x-001", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "authorizationRules": [ + { + "name": "RootManageSharedAccessKey", + "rights": [ + "Listen", + "Manage", + "Send" + ] + }, + { + "name": "AnotherKey", + "rights": [ + "Listen", + "Send" + ] + } + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/deploy.bicep new file mode 100644 index 000000000..13db67e79 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. The name of the authorization rule') +param name string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource authorizationRule 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2017-04-01' = { + name: name + parent: namespace + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/readme.md new file mode 100644 index 000000000..eb25fdcf2 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/readme.md @@ -0,0 +1,43 @@ +# ServiceBus Namespace Authorization Rules `[Microsoft.ServiceBus/namespaces/authorizationRules]` + +This module deploys authorization rules for a service bus namespace + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/AuthorizationRules` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule | +| `namespaceName` | string | Name of the parent Service Bus Namespace for the Service Bus Queue. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | The rights associated with the rule. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/AuthorizationRules) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/authorizationRules/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/deploy.bicep new file mode 100644 index 000000000..8f6bc216f --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/deploy.bicep @@ -0,0 +1,334 @@ +@description('Optional. Name of the Service Bus Namespace. If no name is provided, then unique name will be created.') +@maxLength(50) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Name of this SKU. - Basic, Standard, Premium') +@allowed([ + 'Basic' + 'Standard' + 'Premium' +]) +param skuName string = 'Basic' + +@description('Optional. Enabling this property creates a Premium Service Bus Namespace in regions supported availability zones.') +param zoneRedundant bool = false + +@description('Optional. Authorization Rules for the Service Bus namespace') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } +] + +@description('Optional. IP Filter Rules for the Service Bus namespace') +param ipFilterRules array = [] + +@description('Optional. The migration configuration.') +param migrationConfigurations object = {} + +@description('Optional. The disaster recovery configuration.') +param disasterRecoveryConfigs object = {} + +@description('Optional. vNet Rules SubnetIds for the Service Bus namespace.') +param virtualNetworkRules array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The queues to create in the service bus namespace') +param queues array = [] + +@description('Optional. The topics to create in the service bus namespace') +param topics array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'OperationalLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'OperationalLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var maxNameLength = 50 +var uniqueServiceBusNamespaceNameUntrim = uniqueString('Service Bus Namespace${baseTime}') +var uniqueServiceBusNamespaceName = ((length(uniqueServiceBusNamespaceNameUntrim) > maxNameLength) ? substring(uniqueServiceBusNamespaceNameUntrim, 0, maxNameLength) : uniqueServiceBusNamespaceNameUntrim) + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' = { + name: !empty(name) ? name : uniqueServiceBusNamespaceName + location: location + tags: empty(tags) ? null : tags + sku: { + name: skuName + } + identity: identity + properties: { + zoneRedundant: zoneRedundant + } +} + +module serviceBusNamespace_disasterRecoveryConfig 'disasterRecoveryConfigs/deploy.bicep' = if (!empty(disasterRecoveryConfigs)) { + name: '${uniqueString(deployment().name, location)}-DisasterRecoveryConfig' + params: { + namespaceName: serviceBusNamespace.name + name: contains(disasterRecoveryConfigs, 'name') ? disasterRecoveryConfigs.name : 'default' + alternateName: contains(disasterRecoveryConfigs, 'alternateName') ? disasterRecoveryConfigs.alternateName : '' + partnerNamespaceResourceID: contains(disasterRecoveryConfigs, 'partnerNamespace') ? disasterRecoveryConfigs.partnerNamespace : '' + } +} + +module serviceBusNamespace_migrationConfigurations 'migrationConfigurations/deploy.bicep' = if (!empty(migrationConfigurations)) { + name: '${uniqueString(deployment().name, location)}-MigrationConfigurations' + params: { + namespaceName: serviceBusNamespace.name + name: contains(migrationConfigurations, 'name') ? migrationConfigurations.name : '$default' + postMigrationName: migrationConfigurations.postMigrationName + targetNamespaceResourceId: migrationConfigurations.targetNamespace + } +} + +module serviceBusNamespace_virtualNetworkRules 'virtualNetworkRules/deploy.bicep' = [for (virtualNetworkRule, index) in virtualNetworkRules: { + name: '${uniqueString(deployment().name, location)}-VirtualNetworkRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: last(split(virtualNetworkRule, '/')) + virtualNetworkSubnetId: virtualNetworkRule + } +}] + +module serviceBusNamespace_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${uniqueString(deployment().name, location)}-AuthorizationRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +module serviceBusNamespace_ipFilterRules 'ipFilterRules/deploy.bicep' = [for (ipFilterRule, index) in ipFilterRules: { + name: '${uniqueString(deployment().name, location)}-IpFilterRules-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: contains(ipFilterRule, 'name') ? ipFilterRule.name : ipFilterRule.filterName + action: ipFilterRule.action + filterName: ipFilterRule.filterName + ipMask: ipFilterRule.ipMask + } +}] + +module serviceBusNamespace_queues 'queues/deploy.bicep' = [for (queue, index) in queues: { + name: '${uniqueString(deployment().name, location)}-Queue-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: queue.name + authorizationRules: contains(queue, 'authorizationRules') ? queue.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + deadLetteringOnMessageExpiration: contains(queue, 'deadLetteringOnMessageExpiration') ? queue.deadLetteringOnMessageExpiration : true + defaultMessageTimeToLive: contains(queue, 'defaultMessageTimeToLive') ? queue.defaultMessageTimeToLive : 'P14D' + duplicateDetectionHistoryTimeWindow: contains(queue, 'duplicateDetectionHistoryTimeWindow') ? queue.duplicateDetectionHistoryTimeWindow : 'PT10M' + enableBatchedOperations: contains(queue, 'enableBatchedOperations') ? queue.enableBatchedOperations : true + enableExpress: contains(queue, 'enableExpress') ? queue.enableExpress : false + enablePartitioning: contains(queue, 'enablePartitioning') ? queue.enablePartitioning : false + lock: contains(queue, 'lock') ? queue.lock : 'NotSpecified' + lockDuration: contains(queue, 'lockDuration') ? queue.lockDuration : 'PT1M' + maxDeliveryCount: contains(queue, 'maxDeliveryCount') ? queue.maxDeliveryCount : 10 + maxSizeInMegabytes: contains(queue, 'maxSizeInMegabytes') ? queue.maxSizeInMegabytes : 1024 + requiresDuplicateDetection: contains(queue, 'requiresDuplicateDetection') ? queue.requiresDuplicateDetection : false + requiresSession: contains(queue, 'requiresSession') ? queue.requiresSession : false + roleAssignments: contains(queue, 'roleAssignments') ? queue.roleAssignments : [] + status: contains(queue, 'status') ? queue.status : 'Active' + } +}] + +module serviceBusNamespace_topics 'topics/deploy.bicep' = [for (topic, index) in topics: { + name: '${uniqueString(deployment().name, location)}-Topic-${index}' + params: { + namespaceName: serviceBusNamespace.name + name: topic.name + authorizationRules: contains(topic, 'authorizationRules') ? topic.authorizationRules : [ + { + name: 'RootManageSharedAccessKey' + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + ] + autoDeleteOnIdle: contains(topic, 'autoDeleteOnIdle') ? topic.autoDeleteOnIdle : 'PT5M' + defaultMessageTimeToLive: contains(topic, 'defaultMessageTimeToLive') ? topic.defaultMessageTimeToLive : 'P14D' + duplicateDetectionHistoryTimeWindow: contains(topic, 'duplicateDetectionHistoryTimeWindow') ? topic.duplicateDetectionHistoryTimeWindow : 'PT10M' + enableBatchedOperations: contains(topic, 'enableBatchedOperations') ? topic.enableBatchedOperations : true + enableExpress: contains(topic, 'enableExpress') ? topic.enableExpress : false + enablePartitioning: contains(topic, 'enablePartitioning') ? topic.enablePartitioning : false + lock: contains(topic, 'lock') ? topic.lock : 'NotSpecified' + maxMessageSizeInKilobytes: contains(topic, 'maxMessageSizeInKilobytes') ? topic.maxMessageSizeInKilobytes : 1024 + maxSizeInMegabytes: contains(topic, 'maxSizeInMegabytes') ? topic.maxSizeInMegabytes : 1024 + requiresDuplicateDetection: contains(topic, 'requiresDuplicateDetection') ? topic.requiresDuplicateDetection : false + roleAssignments: contains(topic, 'roleAssignments') ? topic.roleAssignments : [] + status: contains(topic, 'status') ? topic.status : 'Active' + supportOrdering: contains(topic, 'supportOrdering') ? topic.supportOrdering : false + } +}] + +resource serviceBusNamespace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${serviceBusNamespace.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: serviceBusNamespace +} + +resource serviceBusNamespace_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: serviceBusNamespace +} + +module serviceBusNamespace_privateEndpoints '.bicep/nested_privateEndpoints.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: serviceBusNamespace.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpoint: privateEndpoint + tags: tags + } +}] + +module serviceBusNamespace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: serviceBusNamespace.id + } +}] + +@description('The resource ID of the deployed service bus namespace') +output resourceId string = serviceBusNamespace.id + +@description('The resource group of the deployed service bus namespace') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed service bus namespace') +output name string = serviceBusNamespace.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(serviceBusNamespace.identity, 'principalId') ? serviceBusNamespace.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/deploy.bicep new file mode 100644 index 000000000..3290733e4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/deploy.bicep @@ -0,0 +1,50 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the disaster recovery config') +param name string = 'default' + +@description('Optional. Primary/Secondary eventhub namespace name, which is part of GEO DR pairing') +param alternateName string = '' + +@description('Optional. Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing') +param partnerNamespaceResourceID string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource disasterRecoveryConfig 'Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs@2017-04-01' = { + name: name + parent: namespace + properties: { + alternateName: alternateName + partnerNamespace: partnerNamespaceResourceID + } +} + +@description('The name of the disaster recovery config.') +output name string = disasterRecoveryConfig.name + +@description('The Resource ID of the disaster recovery config.') +output resourceId string = disasterRecoveryConfig.id + +@description('The name of the Resource Group the disaster recovery config was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/readme.md new file mode 100644 index 000000000..262eeaf4c --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/readme.md @@ -0,0 +1,44 @@ +# Service Bus Namespace Disaster Recovery Config `[Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs]` + +This module deploys a disaster recovery config for a service bus Namespace + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `namespaceName` | string | Name of the parent Service Bus Namespace for the Service Bus Queue. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `alternateName` | string | `''` | Primary/Secondary eventhub namespace name, which is part of GEO DR pairing | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the disaster recovery config | +| `partnerNamespaceResourceID` | string | `''` | Resource ID of the Primary/Secondary event hub namespace name, which is part of GEO DR pairing | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disaster recovery config. | +| `resourceGroupName` | string | The name of the Resource Group the disaster recovery config was created in. | +| `resourceId` | string | The Resource ID of the disaster recovery config. | + +## Template references + +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/disasterRecoveryConfigs) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/deploy.bicep new file mode 100644 index 000000000..1658d3baa --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/deploy.bicep @@ -0,0 +1,58 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the ip filter rule') +param name string = filterName + +@description('Required. The IP Filter Action') +@allowed([ + 'Accept' + // 'Reject' # Reason: Only Accept IpFilterRules are accepted by API +]) +param action string + +@description('Required. IP Filter name') +param filterName string + +@description('Required. IP Mask') +param ipMask string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource ipFilterRule 'Microsoft.ServiceBus/namespaces/ipFilterRules@2018-01-01-preview' = { + name: name + parent: namespace + properties: { + action: action + filterName: filterName + ipMask: ipMask + } +} + +@description('The name of the IP filter rule.') +output name string = ipFilterRule.name + +@description('The Resource ID of the IP filter rule.') +output resourceId string = ipFilterRule.id + +@description('The name of the Resource Group the IP filter rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/readme.md new file mode 100644 index 000000000..46f9bae43 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/readme.md @@ -0,0 +1,45 @@ +# ServiceBus Namespace Ip-Filter Rules `[Microsoft.ServiceBus/namespaces/ipFilterRules]` + +This module deploys IP filter rules for a service bus namespace + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/ipfilterrules` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `action` | string | `[Accept]` | The IP Filter Action | +| `filterName` | string | | IP Filter name | +| `ipMask` | string | | IP Mask | +| `namespaceName` | string | | Name of the parent Service Bus Namespace for the Service Bus Queue. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[parameters('filterName')]` | The name of the ip filter rule | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the IP filter rule. | +| `resourceGroupName` | string | The name of the Resource Group the IP filter rule was created in. | +| `resourceId` | string | The Resource ID of the IP filter rule. | + +## Template references + +- [Namespaces/Ipfilterrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/ipfilterrules) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/ipFilterRules/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/deploy.bicep new file mode 100644 index 000000000..e082ad8cf --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/deploy.bicep @@ -0,0 +1,50 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the migration configuration') +param name string = '$default' + +@description('Required. Name to access Standard Namespace after migration') +param postMigrationName string + +@description('Required. Existing premium Namespace resource ID which has no entities, will be used for migration') +param targetNamespaceResourceId string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource migrationConfiguration 'Microsoft.ServiceBus/namespaces/migrationConfigurations@2017-04-01' = { + name: name + parent: namespace + properties: { + targetNamespace: targetNamespaceResourceId + postMigrationName: postMigrationName + } +} + +@description('The name of the migration configuration.') +output name string = migrationConfiguration.name + +@description('The Resource ID of the migration configuration') +output resourceId string = migrationConfiguration.id + +@description('The name of the Resource Group the migration configuration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/readme.md new file mode 100644 index 000000000..72b300306 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/readme.md @@ -0,0 +1,44 @@ +# ServiceBus Namespace Migration Configuration `[Microsoft.ServiceBus/namespaces/migrationConfigurations]` + +This module deploys a migration configuration for a service bus namespace + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/migrationConfigurations` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `namespaceName` | string | Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `postMigrationName` | string | Name to access Standard Namespace after migration | +| `targetNamespaceResourceId` | string | Existing premium Namespace resource ID which has no entities, will be used for migration | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'$default'` | The name of the migration configuration | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the migration configuration. | +| `resourceGroupName` | string | The name of the Resource Group the migration configuration was created in. | +| `resourceId` | string | The Resource ID of the migration configuration | + +## Template references + +- [Namespaces/Migrationconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/migrationConfigurations) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/migrationConfigurations/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e182a14e1 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource queue 'Microsoft.ServiceBus/namespaces/queues@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssigment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queue.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: queue +}] diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/deploy.bicep new file mode 100644 index 000000000..6b0bc01b8 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. The name of the service bus namepace queue') +param name string + +@description('Required. The name of the parent service bus namespace') +param namespaceName string + +@description('Required. The name of the parent service bus namespace queue') +param queueName string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource queue 'queues@2021-06-01-preview' existing = { + name: queueName + } +} + +resource authorizationRule 'Microsoft.ServiceBus/namespaces/queues/authorizationRules@2017-04-01' = { + name: name + parent: namespace::queue + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The Resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/readme.md new file mode 100644 index 000000000..f99861781 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/readme.md @@ -0,0 +1,44 @@ +# ServiceBus Namespace Queue Authorization Rules `[Microsoft.ServiceBus/namespaces/queues/authorizationRules]` + +This module deploys an authorization rule for a service bus namespace queue. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/queues/authorizationRules` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the service bus namepace queue | +| `namespaceName` | string | The name of the parent service bus namespace | +| `queueName` | string | The name of the parent service bus namespace queue | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | The rights associated with the rule. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The Resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Queues/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/queues/authorizationRules) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/authorizationRules/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/deploy.bicep new file mode 100644 index 000000000..b16defc0c --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/deploy.bicep @@ -0,0 +1,158 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. Name of the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param name string + +@description('Optional. ISO 8601 timespan duration of a peek-lock; that is, the amount of time that the message is locked for other receivers. The maximum value for LockDuration is 5 minutes; the default value is 1 minute.') +param lockDuration string = 'PT1M' + +@description('Optional. The maximum size of the queue in megabytes, which is the size of memory allocated for the queue. Default is 1024.') +param maxSizeInMegabytes int = 1024 + +@description('Optional. A value indicating if this queue requires duplicate detection.') +param requiresDuplicateDetection bool = false + +@description('Optional. A value that indicates whether the queue supports the concept of sessions.') +param requiresSession bool = false + +@description('Optional. ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself.') +param defaultMessageTimeToLive string = 'P14D' + +@description('Optional. A value that indicates whether this queue has dead letter support when a message expires.') +param deadLetteringOnMessageExpiration bool = true + +@description('Optional. Value that indicates whether server-side batched operations are enabled.') +param enableBatchedOperations bool = true + +@description('Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes.') +param duplicateDetectionHistoryTimeWindow string = 'PT10M' + +@description('Optional. The maximum delivery count. A message is automatically deadlettered after this number of deliveries. default value is 10.') +param maxDeliveryCount int = 10 + +@description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown') +@allowed([ + 'Active' + 'Disabled' + 'Restoring' + 'SendDisabled' + 'ReceiveDisabled' + 'Creating' + 'Deleting' + 'Renaming' + 'Unknown' +]) +param status string = 'Active' + +@description('Optional. A value that indicates whether the queue is to be partitioned across multiple message brokers.') +param enablePartitioning bool = false + +@description('Optional. A value that indicates whether Express Entities are enabled. An express queue holds a message in memory temporarily before writing it to persistent storage.') +param enableExpress bool = false + +@description('Optional. Authorization Rules for the Service Bus Queue') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + } +] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource queue 'Microsoft.ServiceBus/namespaces/queues@2021-06-01-preview' = { + name: name + parent: namespace + properties: { + lockDuration: lockDuration + maxSizeInMegabytes: maxSizeInMegabytes + requiresDuplicateDetection: requiresDuplicateDetection + requiresSession: requiresSession + defaultMessageTimeToLive: defaultMessageTimeToLive + deadLetteringOnMessageExpiration: deadLetteringOnMessageExpiration + enableBatchedOperations: enableBatchedOperations + duplicateDetectionHistoryTimeWindow: duplicateDetectionHistoryTimeWindow + maxDeliveryCount: maxDeliveryCount + status: status + enablePartitioning: enablePartitioning + enableExpress: enableExpress + } +} + +module queue_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + queueName: queue.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +resource queue_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${queue.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: queue +} + +module queue_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: queue.id + } +}] + +@description('The name of the deployed queue') +output name string = queue.name + +@description('The resource ID of the deployed queue') +output resourceId string = queue.id + +@description('The resource group of the deployed queue') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/readme.md new file mode 100644 index 000000000..efe3b1249 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/readme.md @@ -0,0 +1,89 @@ +# ServiceBus Namespace Queue `[Microsoft.ServiceBus/namespaces/queues]` + +This module deploys a queue for a service bus namespace. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ServiceBus/namespaces/queues` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/queues/authorizationRules` | 2017-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Service Bus Queue. | +| `namespaceName` | string | Name of the parent Service Bus Namespace for the Service Bus Queue. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Authorization Rules for the Service Bus Queue | +| `deadLetteringOnMessageExpiration` | bool | `True` | | A value that indicates whether this queue has dead letter support when a message expires. | +| `defaultMessageTimeToLive` | string | `'P14D'` | | ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself. | +| `duplicateDetectionHistoryTimeWindow` | string | `'PT10M'` | | ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes. | +| `enableBatchedOperations` | bool | `True` | | Value that indicates whether server-side batched operations are enabled. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableExpress` | bool | `False` | | A value that indicates whether Express Entities are enabled. An express queue holds a message in memory temporarily before writing it to persistent storage. | +| `enablePartitioning` | bool | `False` | | A value that indicates whether the queue is to be partitioned across multiple message brokers. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `lockDuration` | string | `'PT1M'` | | ISO 8601 timespan duration of a peek-lock; that is, the amount of time that the message is locked for other receivers. The maximum value for LockDuration is 5 minutes; the default value is 1 minute. | +| `maxDeliveryCount` | int | `10` | | The maximum delivery count. A message is automatically deadlettered after this number of deliveries. default value is 10. | +| `maxSizeInMegabytes` | int | `1024` | | The maximum size of the queue in megabytes, which is the size of memory allocated for the queue. Default is 1024. | +| `requiresDuplicateDetection` | bool | `False` | | A value indicating if this queue requires duplicate detection. | +| `requiresSession` | bool | `False` | | A value that indicates whether the queue supports the concept of sessions. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `status` | string | `'Active'` | `[Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown]` | Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed queue | +| `resourceGroupName` | string | The resource group of the deployed queue | +| `resourceId` | string | The resource ID of the deployed queue | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/queues) +- [Namespaces/Queues/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/queues/authorizationRules) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/queues/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/readme.md new file mode 100644 index 000000000..f649c6498 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/readme.md @@ -0,0 +1,191 @@ +# Service Bus Namespaces `[Microsoft.ServiceBus/namespaces]` + +This module deploys a service bus namespace resource. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.ServiceBus/namespaces` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/AuthorizationRules` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/ipfilterrules` | 2018-01-01-preview | +| `Microsoft.ServiceBus/namespaces/migrationConfigurations` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/queues` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/queues/authorizationRules` | 2017-04-01 | +| `Microsoft.ServiceBus/namespaces/topics` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/topics/authorizationRules` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/virtualnetworkrules` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `skuName` | string | `'Basic'` | `[Basic, Standard, Premium]` | Name of this SKU. - Basic, Standard, Premium | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Authorization Rules for the Service Bus namespace | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[OperationalLogs]` | `[OperationalLogs]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disasterRecoveryConfigs` | _[disasterRecoveryConfigs](disasterRecoveryConfigs/readme.md)_ object | `{object}` | | The disaster recovery configuration. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipFilterRules` | _[ipFilterRules](ipFilterRules/readme.md)_ array | `[]` | | IP Filter Rules for the Service Bus namespace | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `migrationConfigurations` | _[migrationConfigurations](migrationConfigurations/readme.md)_ object | `{object}` | | The migration configuration. | +| `name` | string | `''` | | Name of the Service Bus Namespace. If no name is provided, then unique name will be created. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `queues` | _[queues](queues/readme.md)_ array | `[]` | | The queues to create in the service bus namespace | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `topics` | _[topics](topics/readme.md)_ array | `[]` | | The topics to create in the service bus namespace | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `virtualNetworkRules` | _[virtualNetworkRules](virtualNetworkRules/readme.md)_ array | `[]` | | vNet Rules SubnetIds for the Service Bus namespace. | +| `zoneRedundant` | bool | `False` | | Enabling this property creates a Premium Service Bus Namespace in regions supported availability zones. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a SAS token to access the modules. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed service bus namespace | +| `resourceGroupName` | string | The resource group of the deployed service bus namespace | +| `resourceId` | string | The resource ID of the deployed service bus namespace | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces) +- [Namespaces/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/AuthorizationRules) +- [Namespaces/Disasterrecoveryconfigs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/disasterRecoveryConfigs) +- [Namespaces/Ipfilterrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/ipfilterrules) +- [Namespaces/Migrationconfigurations](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/migrationConfigurations) +- [Namespaces/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/queues) +- [Namespaces/Queues/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2017-04-01/namespaces/queues/authorizationRules) +- [Namespaces/Topics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics) +- [Namespaces/Topics/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics/authorizationRules) +- [Namespaces/Virtualnetworkrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/virtualnetworkrules) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d3d8655a1 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource topic 'Microsoft.ServiceBus/namespaces/topics@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssigment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(topic.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: topic +}] diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/deploy.bicep new file mode 100644 index 000000000..1b99a3451 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. The name of the service bus namespace topic') +param name string + +@description('Required. The name of the parent service bus namespace') +param namespaceName string + +@description('Required. The name of the parent service bus namespace topic') +param topicName string + +@description('Optional. The rights associated with the rule.') +@allowed([ + 'Listen' + 'Manage' + 'Send' +]) +param rights array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName + + resource topic 'topics@2021-06-01-preview' existing = { + name: topicName + } +} + +resource authorizationRule 'Microsoft.ServiceBus/namespaces/topics/authorizationRules@2021-06-01-preview' = { + name: name + parent: namespace::topic + properties: { + rights: rights + } +} + +@description('The name of the authorization rule.') +output name string = authorizationRule.name + +@description('The Resource ID of the authorization rule.') +output resourceId string = authorizationRule.id + +@description('The name of the Resource Group the authorization rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/readme.md new file mode 100644 index 000000000..091c5d5bb --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/readme.md @@ -0,0 +1,44 @@ +# ServiceBus Namespace Topic Authorization Rules `[Microsoft.ServiceBus/namespaces/topics/authorizationRules]` + +This module deploys an authorization rule for a service bus namespace topic. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/topics/authorizationRules` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the service bus namespace topic | +| `namespaceName` | string | The name of the parent service bus namespace | +| `topicName` | string | The name of the parent service bus namespace topic | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `rights` | array | `[]` | `[Listen, Manage, Send]` | The rights associated with the rule. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization rule. | +| `resourceGroupName` | string | The name of the Resource Group the authorization rule was created in. | +| `resourceId` | string | The Resource ID of the authorization rule. | + +## Template references + +- [Namespaces/Topics/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics/authorizationRules) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/authorizationRules/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/deploy.bicep new file mode 100644 index 000000000..31da6d97b --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/deploy.bicep @@ -0,0 +1,154 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Topic.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Required. Name of the Service Bus Topic.') +@minLength(6) +@maxLength(50) +param name string + +@description('Optional. The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. Default is 1024.') +param maxSizeInMegabytes int = 1024 + +@description('Optional. A value indicating if this topic requires duplicate detection.') +param requiresDuplicateDetection bool = false + +@description('Optional. ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself.') +param defaultMessageTimeToLive string = 'P14D' + +@description('Optional. Value that indicates whether server-side batched operations are enabled.') +param enableBatchedOperations bool = true + +@description('Optional. ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes.') +param duplicateDetectionHistoryTimeWindow string = 'PT10M' + +@description('Optional. Maximum size (in KB) of the message payload that can be accepted by the topic. This property is only used in Premium today and default is 1024.') +param maxMessageSizeInKilobytes int = 1024 + +@description('Optional. Value that indicates whether the topic supports ordering.') +param supportOrdering bool = false + +@description('Optional. ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes.') +param autoDeleteOnIdle string = 'PT5M' + +@description('Optional. Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown') +@allowed([ + 'Active' + 'Disabled' + 'Restoring' + 'SendDisabled' + 'ReceiveDisabled' + 'Creating' + 'Deleting' + 'Renaming' + 'Unknown' +]) +param status string = 'Active' + +@description('Optional. A value that indicates whether the topic is to be partitioned across multiple message brokers.') +param enablePartitioning bool = false + +@description('Optional. A value that indicates whether Express Entities are enabled. An express topic holds a message in memory temporarily before writing it to persistent storage.') +param enableExpress bool = false + +@description('Optional. Authorization Rules for the Service Bus Topic') +param authorizationRules array = [ + { + name: 'RootManageSharedAccessKey' + properties: { + rights: [ + 'Listen' + 'Manage' + 'Send' + ] + } + } +] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource topic 'Microsoft.ServiceBus/namespaces/topics@2021-06-01-preview' = { + name: name + parent: namespace + properties: { + autoDeleteOnIdle: autoDeleteOnIdle + defaultMessageTimeToLive: defaultMessageTimeToLive + duplicateDetectionHistoryTimeWindow: duplicateDetectionHistoryTimeWindow + enableBatchedOperations: enableBatchedOperations + enableExpress: enableExpress + enablePartitioning: enablePartitioning + maxMessageSizeInKilobytes: maxMessageSizeInKilobytes + maxSizeInMegabytes: maxSizeInMegabytes + requiresDuplicateDetection: requiresDuplicateDetection + status: status + supportOrdering: supportOrdering + } +} + +module topic_authorizationRules 'authorizationRules/deploy.bicep' = [for (authorizationRule, index) in authorizationRules: { + name: '${deployment().name}-AuthRule-${index}' + params: { + namespaceName: namespaceName + topicName: topic.name + name: authorizationRule.name + rights: contains(authorizationRule, 'rights') ? authorizationRule.rights : [] + } +}] + +resource topic_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${topic.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: topic +} + +module topic_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: topic.id + } +}] + +@description('The name of the deployed topic') +output name string = topic.name + +@description('The resource ID of the deployed topic') +output resourceId string = topic.id + +@description('The resource group of the deployed topic') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/readme.md new file mode 100644 index 000000000..3ff37705e --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/readme.md @@ -0,0 +1,88 @@ +# ServiceBus Namespace Topic `[Microsoft.ServiceBus/namespaces/topics]` + +This module deploys a topic for a service bus namespace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ServiceBus/namespaces/topics` | 2021-06-01-preview | +| `Microsoft.ServiceBus/namespaces/topics/authorizationRules` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Service Bus Topic. | +| `namespaceName` | string | Name of the parent Service Bus Namespace for the Service Bus Topic. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authorizationRules` | _[authorizationRules](authorizationRules/readme.md)_ array | `[System.Collections.Hashtable]` | | Authorization Rules for the Service Bus Topic | +| `autoDeleteOnIdle` | string | `'PT5M'` | | ISO 8601 timespan idle interval after which the topic is automatically deleted. The minimum duration is 5 minutes. | +| `defaultMessageTimeToLive` | string | `'P14D'` | | ISO 8601 default message timespan to live value. This is the duration after which the message expires, starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself. | +| `duplicateDetectionHistoryTimeWindow` | string | `'PT10M'` | | ISO 8601 timeSpan structure that defines the duration of the duplicate detection history. The default value is 10 minutes. | +| `enableBatchedOperations` | bool | `True` | | Value that indicates whether server-side batched operations are enabled. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableExpress` | bool | `False` | | A value that indicates whether Express Entities are enabled. An express topic holds a message in memory temporarily before writing it to persistent storage. | +| `enablePartitioning` | bool | `False` | | A value that indicates whether the topic is to be partitioned across multiple message brokers. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxMessageSizeInKilobytes` | int | `1024` | | Maximum size (in KB) of the message payload that can be accepted by the topic. This property is only used in Premium today and default is 1024. | +| `maxSizeInMegabytes` | int | `1024` | | The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. Default is 1024. | +| `requiresDuplicateDetection` | bool | `False` | | A value indicating if this topic requires duplicate detection. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `status` | string | `'Active'` | `[Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown]` | Enumerates the possible values for the status of a messaging entity. - Active, Disabled, Restoring, SendDisabled, ReceiveDisabled, Creating, Deleting, Renaming, Unknown | +| `supportOrdering` | bool | `False` | | Value that indicates whether the topic supports ordering. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed topic | +| `resourceGroupName` | string | The resource group of the deployed topic | +| `resourceId` | string | The resource ID of the deployed topic | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Namespaces/Topics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics) +- [Namespaces/Topics/Authorizationrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2021-06-01-preview/namespaces/topics/authorizationRules) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/topics/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/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/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/deploy.bicep b/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/deploy.bicep new file mode 100644 index 000000000..40efd723e --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/deploy.bicep @@ -0,0 +1,46 @@ +@description('Required. Name of the parent Service Bus Namespace for the Service Bus Queue.') +@minLength(6) +@maxLength(50) +param namespaceName string + +@description('Optional. The name of the virtual network rule') +param name string = '${namespaceName}-vnr' + +@description('Required. Resource ID of Virtual Network Subnet') +param virtualNetworkSubnetId string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' existing = { + name: namespaceName +} + +resource virtualNetworkRule 'Microsoft.ServiceBus/namespaces/virtualNetworkRules@2018-01-01-preview' = { + name: name + parent: namespace + properties: { + virtualNetworkSubnetId: virtualNetworkSubnetId + } +} + +@description('The name of the virtual network rule.') +output name string = virtualNetworkRule.name + +@description('The Resource ID of the virtual network rule.') +output resourceId string = virtualNetworkRule.id + +@description('The name of the Resource Group the virtual network rule was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/readme.md b/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/readme.md new file mode 100644 index 000000000..d5796115c --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/readme.md @@ -0,0 +1,43 @@ +# ServiceBus Namespace Virtual Network Rules `[Microsoft.ServiceBus/namespaces/virtualNetworkRules]` + +This module deploys a virtual network rule for a service bus namespace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceBus/namespaces/virtualnetworkrules` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `namespaceName` | string | Name of the parent Service Bus Namespace for the Service Bus Queue. | +| `virtualNetworkSubnetId` | string | Resource ID of Virtual Network Subnet | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[format('{0}-vnr', parameters('namespaceName'))]` | The name of the virtual network rule | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network rule. | +| `resourceGroupName` | string | The name of the Resource Group the virtual network rule was created in. | +| `resourceId` | string | The Resource ID of the virtual network rule. | + +## Template references + +- [Namespaces/Virtualnetworkrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceBus/2018-01-01-preview/namespaces/virtualnetworkrules) diff --git a/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/version.json b/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceBus/namespaces/virtualNetworkRules/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/carml/1.0.1/Microsoft.ServiceFabric/clusters/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4fed3f7b2 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = [for principalId in principalIds: { + name: guid(serviceFabricCluster.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: serviceFabricCluster +}] diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/cert.parameters.json b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/cert.parameters.json new file mode 100644 index 000000000..668b6d8d1 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/cert.parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sfc-cert-001" + }, + "managementEndpoint": { + "value": "https://<>-az-sfc-cert-001.westeurope.cloudapp.azure.com:19080" + }, + "reliabilityLevel": { + "value": "None" + }, + "certificate": { + "value": { + "thumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", // Mutual exclusive with the other cert specs + "x509StoreName": "My" + } + }, + "nodeTypes": { + "value": [ + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": 65534, + "startPort": 49152 + }, + "httpGatewayEndpointPort": 19080, + "isPrimary": true, + "name": "Node01" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/full.parameters.json b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/full.parameters.json new file mode 100644 index 000000000..6a7a61614 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/full.parameters.json @@ -0,0 +1,205 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sfc-full-001" + }, + "tags": { + "value": { + "resourceType": "Service Fabric", + "clusterName": "<>-az-sfc-full-001" + } + }, + "addOnFeatures": { + "value": [ + "RepairManager", + "DnsService", + "BackupRestoreService", + "ResourceMonitorService" + ] + }, + "maxUnusedVersionsToKeep": { + "value": 2 + }, + "azureActiveDirectory": { + "value": { + "clientApplication": "<>", + "clusterApplication": "cf33fea8-b30f-424f-ab73-c48d99e0b222", + "tenantId": "<>" + } + }, + "certificateCommonNames": { + "value": { + "commonNames": [ + { + "certificateCommonName": "certcommon", + "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130" + } + ], + "x509StoreName": "" + } + }, + "clientCertificateCommonNames": { + "value": [ + { + "certificateCommonName": "clientcommoncert1", + "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", + "isAdmin": false + }, + { + "certificateCommonName": "clientcommoncert2", + "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC131", + "isAdmin": false + } + ] + }, + "clientCertificateThumbprints": { + "value": [ + { + "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", + "isAdmin": false + }, + { + "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC131", + "isAdmin": false + } + ] + }, + "diagnosticsStorageAccountConfig": { + "value": { + "blobEndpoint": "https://adp<>azsaweux001.blob.core.windows.net/", + "protectedAccountKeyName": "StorageAccountKey1", + "queueEndpoint": "https://adp<>azsaweux001.queue.core.windows.net/", + "storageAccountName": "adp<>azsaweux001", + "tableEndpoint": "https://adp<>azsaweux001.table.core.windows.net/" + } + }, + "fabricSettings": { + "value": [ + { + "name": "Security", + "parameters": [ + { + "name": "ClusterProtectionLevel", + "value": "EncryptAndSign" + } + ] + }, + { + "name": "UpgradeService", + "parameters": [ + { + "name": "AppPollIntervalInSeconds", + "value": "60" + } + ] + } + ] + }, + "managementEndpoint": { + "value": "https://<>-az-sfc-full-001.westeurope.cloudapp.azure.com:19080" + }, + "nodeTypes": { + "value": [ + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "capacities": {}, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Silver", + "ephemeralPorts": { + "endPort": 65534, + "startPort": 49152 + }, + "httpGatewayEndpointPort": 19080, + "isPrimary": true, + "isStateless": false, + "multipleAvailabilityZones": false, + "name": "Node01", + "placementProperties": {}, + "reverseProxyEndpointPort": "", + "vmInstanceCount": 5 + }, + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": 64000, + "startPort": 49000 + }, + "httpGatewayEndpointPort": 19007, + "isPrimary": true, + "name": "Node02", + "vmInstanceCount": 5 + } + ] + }, + "notifications": { + "value": [ + { + "isEnabled": true, + "notificationCategory": "WaveProgress", + "notificationLevel": "Critical", + "notificationTargets": [ + { + "notificationChannel": "EmailUser", + "receivers": [ + "SomeReceiver" + ] + } + ] + } + ] + }, + "upgradeDescription": { + "value": { + "forceRestart": false, + "upgradeReplicaSetCheckTimeout": "1.00:00:00", + "healthCheckWaitDuration": "00:00:30", + "healthCheckStableDuration": "00:01:00", + "healthCheckRetryTimeout": "00:45:00", + "upgradeTimeout": "02:00:00", + "upgradeDomainTimeout": "02:00:00", + "healthPolicy": { + "maxPercentUnhealthyNodes": 0, + "maxPercentUnhealthyApplications": 0 + }, + "deltaHealthPolicy": { + "maxPercentDeltaUnhealthyNodes": 0, + "maxPercentUpgradeDomainDeltaUnhealthyNodes": 0, + "maxPercentDeltaUnhealthyApplications": 0 + } + } + }, + "reliabilityLevel": { + "value": "Silver" + }, + "vmImage": { + "value": "Linux" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "applicationTypes": { + "value": [ + { + "name": "WordCount" // not idempotent + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/min.parameters.json new file mode 100644 index 000000000..b7673a725 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/.parameters/min.parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sfc-min-001" + }, + "managementEndpoint": { + "value": "https://<>-az-sfc-min-001.westeurope.cloudapp.azure.com:19080" + }, + "reliabilityLevel": { + "value": "None" + }, + "nodeTypes": { + "value": [ + { + "applicationPorts": { + "endPort": 30000, + "startPort": 20000 + }, + "clientConnectionEndpointPort": 19000, + "durabilityLevel": "Bronze", + "ephemeralPorts": { + "endPort": 65534, + "startPort": 49152 + }, + "httpGatewayEndpointPort": 19080, + "isPrimary": true, + "name": "Node01" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/deploy.bicep b/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/deploy.bicep new file mode 100644 index 000000000..9e56b88bd --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/deploy.bicep @@ -0,0 +1,42 @@ +@description('Required. Name of the Service Fabric cluster.') +param serviceFabricClusterName string = '' + +@description('Optional. Application type name.') +param name string = 'defaultApplicationType' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' existing = { + name: serviceFabricClusterName +} + +resource applicationTypes 'Microsoft.ServiceFabric/clusters/applicationTypes@2021-06-01' = { + name: name + parent: serviceFabricCluster + tags: tags +} + +@description('The resource name of the Application type.') +output name string = applicationTypes.name + +@description('The resource group of the Application type.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the Application type.') +output resourceID string = applicationTypes.id diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/readme.md b/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/readme.md new file mode 100644 index 000000000..da550666a --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/readme.md @@ -0,0 +1,60 @@ +# Service Fabric Cluster Application Types `[Microsoft.ServiceFabric/clusters/applicationTypes]` + +This module deploys a Service Fabric Cluster Application Type. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ServiceFabric/clusters/applicationTypes` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `serviceFabricClusterName` | string | `''` | Name of the Service Fabric cluster. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'defaultApplicationType'` | Application type name. | +| `tags` | object | `{object}` | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The resource name of the Application type. | +| `resourceGroupName` | string | The resource group of the Application type. | +| `resourceID` | string | The resource ID of the Application type. | + +## Template references + +- [Clusters/Applicationtypes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceFabric/2021-06-01/clusters/applicationTypes) diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/version.json b/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/applicationTypes/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/carml/1.0.1/Microsoft.ServiceFabric/clusters/deploy.bicep b/carml/1.0.1/Microsoft.ServiceFabric/clusters/deploy.bicep new file mode 100644 index 000000000..f950d687f --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/deploy.bicep @@ -0,0 +1,322 @@ +@description('Required. Name of the Service Fabric cluster.') +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@allowed([ + 'BackupRestoreService' + 'DnsService' + 'RepairManager' + 'ResourceMonitorService' +]) +@description('Optional. The list of add-on features to enable in the cluster.') +param addOnFeatures array = [] + +@description('Required. Number of unused versions per application type to keep.') +param maxUnusedVersionsToKeep int = 3 + +@description('Optional. The settings to enable AAD authentication on the cluster.') +param azureActiveDirectory object = {} + +@description('Optional. Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location') +param certificate object = {} + +@description('Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster.') +param certificateCommonNames object = {} + +@description('Optional. The list of client certificates referenced by common name that are allowed to manage the cluster.') +param clientCertificateCommonNames array = [] + +@description('Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster.') +param clientCertificateThumbprints array = [] + +@description('Optional. The Service Fabric runtime version of the cluster. This property can only by set the user when upgradeMode is set to "Manual". To get list of available Service Fabric versions for new clusters use ClusterVersion API. To get the list of available version for existing clusters use availableClusterVersions.') +param clusterCodeVersion string = '' + +@description('Optional. The storage account information for storing Service Fabric diagnostic logs.') +param diagnosticsStorageAccountConfig object = {} + +@description('Optional. Indicates if the event store service is enabled.') +param eventStoreServiceEnabled bool = false + +@description('Optional. The list of custom fabric settings to configure the cluster.') +param fabricSettings array = [] + +@description('Optional. Indicates if infrastructure service manager is enabled.') +param infrastructureServiceManager bool = false + +@description('Required. The http management endpoint of the cluster.') +param managementEndpoint string + +@description('Required. The list of node types in the cluster.') +param nodeTypes array = [] + +@description('Optional. Indicates a list of notification channels for cluster events.') +param notifications array = [] + +@allowed([ + 'Bronze' + 'Gold' + 'None' + 'Platinum' + 'Silver' +]) +@description('Optional. The reliability level sets the replica set size of system services. Learn about ReliabilityLevel (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-capacity). - None - Run the System services with a target replica set count of 1. This should only be used for test clusters. - Bronze - Run the System services with a target replica set count of 3. This should only be used for test clusters. - Silver - Run the System services with a target replica set count of 5. - Gold - Run the System services with a target replica set count of 7. - Platinum - Run the System services with a target replica set count of 9.') +param reliabilityLevel string + +@description('Optional. Describes the certificate details.') +param reverseProxyCertificate object = {} + +@description('Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster.') +param reverseProxyCertificateCommonNames object = {} + +@allowed([ + 'Hierarchical' + 'Parallel' +]) +@description('Optional. This property controls the logical grouping of VMs in upgrade domains (UDs). This property cannot be modified if a node type with multiple Availability Zones is already present in the cluster.') +param sfZonalUpgradeMode string = 'Hierarchical' + +@description('Optional. Describes the policy used when upgrading the cluster.') +param upgradeDescription object = {} + +@allowed([ + 'Automatic' + 'Manual' +]) +@description('Optional. The upgrade mode of the cluster when new Service Fabric runtime version is available.') +param upgradeMode string = 'Automatic' + +@description('Optional. Indicates the end date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC).') +param upgradePauseEndTimestampUtc string = '' + +@description('Optional. Indicates the start date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC).') +param upgradePauseStartTimestampUtc string = '' + +@allowed([ + 'Wave0' + 'Wave1' + 'Wave2' +]) +@description('Optional. Indicates when new cluster runtime version upgrades will be applied after they are released. By default is Wave0.') +param upgradeWave string = 'Wave0' + +@description('Optional. The VM image VMSS has been configured with. Generic names such as Windows or Linux can be used') +param vmImage string = '' + +@allowed([ + 'Hierarchical' + 'Parallel' +]) +@description('Optional. This property defines the upgrade mode for the virtual machine scale set, it is mandatory if a node type with multiple Availability Zones is added.') +param vmssZonalUpgradeMode string = 'Hierarchical' + +@description('Optional. Boolean to pause automatic runtime version upgrades to the cluster.') +param waveUpgradePaused bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Array of Service Fabric cluster application types.') +param applicationTypes array = [] + +var clientCertificateCommonNames_var = [for clientCertificateCommonName in clientCertificateCommonNames: { + certificateCommonName: contains(clientCertificateCommonName, 'certificateCommonName') ? clientCertificateCommonName.certificateCommonName : null + certificateIssuerThumbprint: contains(clientCertificateCommonName, 'certificateIssuerThumbprint') ? clientCertificateCommonName.certificateIssuerThumbprint : null + isAdmin: contains(clientCertificateCommonName, 'isAdmin') ? clientCertificateCommonName.isAdmin : false +}] + +var clientCertificateThumbprints_var = [for clientCertificateThumbprint in clientCertificateThumbprints: { + certificateThumbprint: contains(clientCertificateThumbprint, 'certificateThumbprint') ? clientCertificateThumbprint.certificateThumbprint : null + isAdmin: contains(clientCertificateThumbprint, 'isAdmin') ? clientCertificateThumbprint.isAdmin : false +}] + +var fabricSettings_var = [for fabricSetting in fabricSettings: { + name: contains(fabricSetting, 'name') ? fabricSetting.name : null + parameters: contains(fabricSetting, 'parameters') ? fabricSetting.parameters : null +}] + +var nodeTypes_var = [for nodeType in nodeTypes: { + applicationPorts: contains(nodeType, 'applicationPorts') ? { + endPort: contains(nodeType.applicationPorts, 'endPort') ? nodeType.applicationPorts.endPort : null + startPort: contains(nodeType.applicationPorts, 'startPort') ? nodeType.applicationPorts.startPort : null + } : null + capacities: contains(nodeType, 'capacities') ? nodeType.capacities : null + clientConnectionEndpointPort: contains(nodeType, 'clientConnectionEndpointPort') ? nodeType.clientConnectionEndpointPort : null + durabilityLevel: contains(nodeType, 'durabilityLevel') ? nodeType.durabilityLevel : null + ephemeralPorts: contains(nodeType, 'ephemeralPorts') ? { + endPort: contains(nodeType.ephemeralPorts, 'endPort') ? nodeType.ephemeralPorts.endPort : null + startPort: contains(nodeType.ephemeralPorts, 'startPort') ? nodeType.ephemeralPorts.startPort : null + } : null + httpGatewayEndpointPort: contains(nodeType, 'httpGatewayEndpointPort') ? nodeType.httpGatewayEndpointPort : null + isPrimary: contains(nodeType, 'isPrimary') ? nodeType.isPrimary : null + isStateless: contains(nodeType, 'isStateless') ? nodeType.isStateless : null + multipleAvailabilityZones: contains(nodeType, 'multipleAvailabilityZones') ? nodeType.multipleAvailabilityZones : null + name: contains(nodeType, 'name') ? nodeType.name : 'Node00' + placementProperties: contains(nodeType, 'placementProperties') ? nodeType.placementProperties : null + reverseProxyEndpointPort: contains(nodeType, 'reverseProxyEndpointPort') ? nodeType.reverseProxyEndpointPort : null + vmInstanceCount: contains(nodeType, 'vmInstanceCount') ? nodeType.vmInstanceCount : 1 +}] + +var notifications_var = [for notification in notifications: { + isEnabled: contains(notification, 'isEnabled') ? notification.isEnabled : false + notificationCategory: contains(notification, 'notificationCategory') ? notification.notificationCategory : 'WaveProgress' + notificationLevel: contains(notification, 'notificationLevel') ? notification.notificationLevel : 'All' + notificationTargets: contains(notification, 'notificationTargets') ? notification.notificationTargets : [] +}] + +var upgradeDescription_var = union({ + deltaHealthPolicy: { + applicationDeltaHealthPolicies: contains(upgradeDescription, 'applicationDeltaHealthPolicies') ? upgradeDescription.applicationDeltaHealthPolicies : {} + maxPercentDeltaUnhealthyApplications: contains(upgradeDescription, 'maxPercentDeltaUnhealthyApplications') ? upgradeDescription.maxPercentDeltaUnhealthyApplications : 0 + maxPercentDeltaUnhealthyNodes: contains(upgradeDescription, 'maxPercentDeltaUnhealthyNodes') ? upgradeDescription.maxPercentDeltaUnhealthyNodes : 0 + maxPercentUpgradeDomainDeltaUnhealthyNodes: contains(upgradeDescription, 'maxPercentUpgradeDomainDeltaUnhealthyNodes') ? upgradeDescription.maxPercentUpgradeDomainDeltaUnhealthyNodes : 0 + } + forceRestart: contains(upgradeDescription, 'forceRestart') ? upgradeDescription.forceRestart : false + healthCheckRetryTimeout: contains(upgradeDescription, 'healthCheckRetryTimeout') ? upgradeDescription.healthCheckRetryTimeout : '00:45:00' + healthCheckStableDuration: contains(upgradeDescription, 'healthCheckStableDuration') ? upgradeDescription.healthCheckStableDuration : '00:01:00' + healthCheckWaitDuration: contains(upgradeDescription, 'healthCheckWaitDuration') ? upgradeDescription.healthCheckWaitDuration : '00:00:30' + upgradeDomainTimeout: contains(upgradeDescription, 'upgradeDomainTimeout') ? upgradeDescription.upgradeDomainTimeout : '02:00:00' + upgradeReplicaSetCheckTimeout: contains(upgradeDescription, 'upgradeReplicaSetCheckTimeout') ? upgradeDescription.upgradeReplicaSetCheckTimeout : '1.00:00:00' + upgradeTimeout: contains(upgradeDescription, 'upgradeTimeout') ? upgradeDescription.upgradeTimeout : '02:00:00' +}, contains(upgradeDescription, 'healthPolicy') ? { + healthPolicy: { + applicationHealthPolicies: contains(upgradeDescription.healthPolicy, 'applicationHealthPolicies') ? upgradeDescription.healthPolicy.applicationHealthPolicies : {} + maxPercentUnhealthyApplications: contains(upgradeDescription.healthPolicy, 'maxPercentUnhealthyApplications') ? upgradeDescription.healthPolicy.maxPercentUnhealthyApplications : 0 + maxPercentUnhealthyNodes: contains(upgradeDescription.healthPolicy, 'maxPercentUnhealthyNodes') ? upgradeDescription.healthPolicy.maxPercentUnhealthyNodes : 0 + } +} : {}) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +// Service Fabric cluster resource +resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' = { + name: name + location: location + tags: tags + properties: { + addOnFeatures: addOnFeatures + applicationTypeVersionsCleanupPolicy: { + maxUnusedVersionsToKeep: maxUnusedVersionsToKeep + } + azureActiveDirectory: !empty(azureActiveDirectory) ? { + clientApplication: contains(azureActiveDirectory, 'clientApplication') ? azureActiveDirectory.clientApplication : null + clusterApplication: contains(azureActiveDirectory, 'clusterApplication') ? azureActiveDirectory.clusterApplication : null + tenantId: contains(azureActiveDirectory, 'tenantId') ? azureActiveDirectory.tenantId : null + } : null + certificate: !empty(certificate) ? { + thumbprint: contains(certificate, 'thumbprint') ? certificate.thumbprint : null + thumbprintSecondary: contains(certificate, 'thumbprintSecondary') ? certificate.thumbprintSecondary : null + x509StoreName: contains(certificate, 'x509StoreName') ? certificate.x509StoreName : null + } : null + certificateCommonNames: !empty(certificateCommonNames) ? { + commonNames: contains(certificateCommonNames, 'commonNames') ? certificateCommonNames.commonNames : null + x509StoreName: contains(certificateCommonNames, 'certificateCommonNamesx509StoreName') ? certificateCommonNames.certificateCommonNamesx509StoreName : null + } : null + clientCertificateCommonNames: !empty(clientCertificateCommonNames) ? clientCertificateCommonNames_var : null + clientCertificateThumbprints: !empty(clientCertificateThumbprints) ? clientCertificateThumbprints_var : null + clusterCodeVersion: !empty(clusterCodeVersion) ? clusterCodeVersion : null + diagnosticsStorageAccountConfig: !empty(diagnosticsStorageAccountConfig) ? { + blobEndpoint: contains(diagnosticsStorageAccountConfig, 'blobEndpoint') ? diagnosticsStorageAccountConfig.blobEndpoint : null + protectedAccountKeyName: contains(diagnosticsStorageAccountConfig, 'protectedAccountKeyName') ? diagnosticsStorageAccountConfig.protectedAccountKeyName : null + protectedAccountKeyName2: contains(diagnosticsStorageAccountConfig, 'protectedAccountKeyName2') ? diagnosticsStorageAccountConfig.protectedAccountKeyName2 : null + queueEndpoint: contains(diagnosticsStorageAccountConfig, 'queueEndpoint') ? diagnosticsStorageAccountConfig.queueEndpoint : null + storageAccountName: contains(diagnosticsStorageAccountConfig, 'storageAccountName') ? diagnosticsStorageAccountConfig.storageAccountName : null + tableEndpoint: contains(diagnosticsStorageAccountConfig, 'tableEndpoint') ? diagnosticsStorageAccountConfig.tableEndpoint : null + } : null + eventStoreServiceEnabled: eventStoreServiceEnabled + fabricSettings: !empty(fabricSettings) ? fabricSettings_var : null + infrastructureServiceManager: infrastructureServiceManager + managementEndpoint: managementEndpoint + nodeTypes: !empty(nodeTypes) ? nodeTypes_var : [] + notifications: !empty(notifications) ? notifications_var : null + reliabilityLevel: !empty(reliabilityLevel) ? reliabilityLevel : 'None' + reverseProxyCertificate: !empty(reverseProxyCertificate) ? { + thumbprint: contains(reverseProxyCertificate, 'thumbprint') ? reverseProxyCertificate.thumbprint : null + thumbprintSecondary: contains(reverseProxyCertificate, 'thumbprintSecondary') ? reverseProxyCertificate.thumbprintSecondary : null + x509StoreName: contains(reverseProxyCertificate, 'x509StoreName') ? reverseProxyCertificate.x509StoreName : null + } : null + reverseProxyCertificateCommonNames: !empty(reverseProxyCertificateCommonNames) ? { + commonNames: contains(reverseProxyCertificateCommonNames, 'commonNames') ? reverseProxyCertificateCommonNames.commonNames : null + x509StoreName: contains(reverseProxyCertificateCommonNames, 'x509StoreName') ? reverseProxyCertificateCommonNames.x509StoreName : null + } : null + sfZonalUpgradeMode: !empty(sfZonalUpgradeMode) ? sfZonalUpgradeMode : null + upgradeDescription: !empty(upgradeDescription) ? upgradeDescription_var : null + upgradeMode: !empty(upgradeMode) ? upgradeMode : null + upgradePauseEndTimestampUtc: !empty(upgradePauseEndTimestampUtc) ? upgradePauseEndTimestampUtc : null + upgradePauseStartTimestampUtc: !empty(upgradePauseStartTimestampUtc) ? upgradePauseStartTimestampUtc : null + upgradeWave: !empty(upgradeWave) ? upgradeWave : null + vmImage: !empty(vmImage) ? vmImage : null + vmssZonalUpgradeMode: !empty(vmssZonalUpgradeMode) ? vmssZonalUpgradeMode : null + waveUpgradePaused: waveUpgradePaused + } +} + +// Service Fabric cluster resource lock +resource serviceFabricCluster_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${serviceFabricCluster.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: serviceFabricCluster +} + +// Service Fabric cluster RBAC assignment +module serviceFabricCluster_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ServiceFabric-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: serviceFabricCluster.id + } +}] + +// Service Fabric cluster application types +module serviceFabricCluster_applicationTypes 'applicationTypes/deploy.bicep' = [for applicationType in applicationTypes: { + name: '${uniqueString(deployment().name, location)}-SFC-${applicationType.name}' + params: { + name: applicationType.name + serviceFabricClusterName: serviceFabricCluster.name + tags: contains(applicationType, 'tags') ? applicationType.tags : {} + } +}] + +@description('The Service Fabric Cluster name.') +output name string = serviceFabricCluster.name + +@description('The Service Fabric Cluster resource group.') +output resourceGroupName string = resourceGroup().name + +@description('The Service Fabric Cluster resource ID.') +output resourceId string = serviceFabricCluster.id + +@description('The Service Fabric Cluster endpoint.') +output endpoint string = serviceFabricCluster.properties.clusterEndpoint diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/readme.md b/carml/1.0.1/Microsoft.ServiceFabric/clusters/readme.md new file mode 100644 index 000000000..20534ae57 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/readme.md @@ -0,0 +1,145 @@ +# Service Fabric Clusters `[Microsoft.ServiceFabric/clusters]` + +This module deploys a Service Fabric Cluster. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2020-04-01-preview | +| `Microsoft.ServiceFabric/clusters` | 2021-06-01 | +| `Microsoft.ServiceFabric/clusters/applicationTypes` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `managementEndpoint` | string | | The http management endpoint of the cluster. | +| `maxUnusedVersionsToKeep` | int | `3` | Number of unused versions per application type to keep. | +| `name` | string | `''` | Name of the Service Fabric cluster. | +| `nodeTypes` | array | `[]` | The list of node types in the cluster. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addOnFeatures` | array | `[]` | `[BackupRestoreService, DnsService, RepairManager, ResourceMonitorService]` | The list of add-on features to enable in the cluster. | +| `applicationTypes` | _[applicationTypes](applicationTypes/readme.md)_ array | `[]` | | Array of Service Fabric cluster application types. | +| `azureActiveDirectory` | object | `{object}` | | The settings to enable AAD authentication on the cluster. | +| `certificate` | object | `{object}` | | Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location | +| `certificateCommonNames` | object | `{object}` | | Describes a list of server certificates referenced by common name that are used to secure the cluster. | +| `clientCertificateCommonNames` | array | `[]` | | The list of client certificates referenced by common name that are allowed to manage the cluster. | +| `clientCertificateThumbprints` | array | `[]` | | The list of client certificates referenced by thumbprint that are allowed to manage the cluster. | +| `clusterCodeVersion` | string | `''` | | The Service Fabric runtime version of the cluster. This property can only by set the user when upgradeMode is set to "Manual". To get list of available Service Fabric versions for new clusters use ClusterVersion API. To get the list of available version for existing clusters use availableClusterVersions. | +| `diagnosticsStorageAccountConfig` | object | `{object}` | | The storage account information for storing Service Fabric diagnostic logs. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `eventStoreServiceEnabled` | bool | `False` | | Indicates if the event store service is enabled. | +| `fabricSettings` | array | `[]` | | The list of custom fabric settings to configure the cluster. | +| `infrastructureServiceManager` | bool | `False` | | Indicates if infrastructure service manager is enabled. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `notifications` | array | `[]` | | Indicates a list of notification channels for cluster events. | +| `reliabilityLevel` | string | | `[Bronze, Gold, None, Platinum, Silver]` | The reliability level sets the replica set size of system services. Learn about ReliabilityLevel (https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-capacity). - None - Run the System services with a target replica set count of 1. This should only be used for test clusters. - Bronze - Run the System services with a target replica set count of 3. This should only be used for test clusters. - Silver - Run the System services with a target replica set count of 5. - Gold - Run the System services with a target replica set count of 7. - Platinum - Run the System services with a target replica set count of 9. | +| `reverseProxyCertificate` | object | `{object}` | | Describes the certificate details. | +| `reverseProxyCertificateCommonNames` | object | `{object}` | | Describes a list of server certificates referenced by common name that are used to secure the cluster. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sfZonalUpgradeMode` | string | `'Hierarchical'` | `[Hierarchical, Parallel]` | This property controls the logical grouping of VMs in upgrade domains (UDs). This property cannot be modified if a node type with multiple Availability Zones is already present in the cluster. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `upgradeDescription` | object | `{object}` | | Describes the policy used when upgrading the cluster. | +| `upgradeMode` | string | `'Automatic'` | `[Automatic, Manual]` | The upgrade mode of the cluster when new Service Fabric runtime version is available. | +| `upgradePauseEndTimestampUtc` | string | `''` | | Indicates the end date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC). | +| `upgradePauseStartTimestampUtc` | string | `''` | | Indicates the start date and time to pause automatic runtime version upgrades on the cluster for an specific period of time on the cluster (UTC). | +| `upgradeWave` | string | `'Wave0'` | `[Wave0, Wave1, Wave2]` | Indicates when new cluster runtime version upgrades will be applied after they are released. By default is Wave0. | +| `vmImage` | string | `''` | | The VM image VMSS has been configured with. Generic names such as Windows or Linux can be used | +| `vmssZonalUpgradeMode` | string | `'Hierarchical'` | `[Hierarchical, Parallel]` | This property defines the upgrade mode for the virtual machine scale set, it is mandatory if a node type with multiple Availability Zones is added. | +| `waveUpgradePaused` | bool | `False` | | Boolean to pause automatic runtime version upgrades to the cluster. | + + +### Parameter Usage: `notifications` + +```json +"notifications": { + "value": [ + { + "isEnabled": true, // Required. Indicates if the notification is enabled. + "notificationCategory": "WaveProgress", // Required. The category of notification. Possible values include: "WaveProgress". + "notificationLevel": "Critical", // Required. The level of notification. Possible values include: "Critical", "All". + "notificationTargets": [ + { + "notificationChannel": "EmailUser", // Required. The notification channel indicates the type of receivers subscribed to the notification, either user or subscription. Possible values include: "EmailUser", "EmailSubscription". + "receivers": [ + "SomeReceiver" // Required. List of targets that subscribe to the notification. + ] + } + ] + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `endpoint` | string | The Service Fabric Cluster endpoint. | +| `name` | string | The Service Fabric Cluster name. | +| `resourceGroupName` | string | The Service Fabric Cluster resource group. | +| `resourceId` | string | The Service Fabric Cluster resource ID. | + +## Template references + +- [Clusters](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceFabric/2021-06-01/clusters) +- [Clusters/Applicationtypes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ServiceFabric/2021-06-01/clusters/applicationTypes) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-04-01-preview/roleAssignments) diff --git a/carml/1.0.1/Microsoft.ServiceFabric/clusters/version.json b/carml/1.0.1/Microsoft.ServiceFabric/clusters/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.ServiceFabric/clusters/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/carml/1.0.1/Microsoft.Sql/managedInstances/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..eceb898e7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2020-08-01-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(managedInstance.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: managedInstance +}] diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/.parameters/parameters.json b/carml/1.0.1/Microsoft.Sql/managedInstances/.parameters/parameters.json new file mode 100644 index 000000000..d6eef2990 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/.parameters/parameters.json @@ -0,0 +1,147 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sqlmi-x-002" + }, + "administratorLogin": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLogin" + } + }, + "administratorLoginPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLoginPassword" + } + }, + "subnetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-sqlmi/subnets/<>-az-subnet-x-sqlmi" + }, + "skuName": { + "value": "GP_Gen5" + }, + "skuTier": { + "value": "GeneralPurpose" + }, + "storageSizeInGB": { + "value": 32 + }, + "vCores": { + "value": 4 + }, + "licenseType": { + "value": "LicenseIncluded" + }, + "hardwareFamily": { + "value": "Gen5" + }, + "servicePrincipal": { + "value": "SystemAssigned" + }, + "dnsZonePartner": { + "value": "" + }, + "timezoneId": { + "value": "UTC" + }, + "collation": { + "value": "SQL_Latin1_General_CP1_CI_AS" + }, + "proxyOverride": { + "value": "Proxy" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "primaryUserAssignedIdentityId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001" + }, + "publicDataEndpointEnabled": { + "value": false + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "keys": { + "value": [ + { + "name": "adp-<>-az-kv-x-sqlmi_keyEncryptionKeySqlMi_4bf367f64c914d8ba698700fb598ad07", // ID must be updated for new keys + "uri": "https://adp-<>-az-kv-x-sqlmi.vault.azure.net/keys/keyEncryptionKeySqlMi/4bf367f64c914d8ba698700fb598ad07", // ID must be updated for new keys + "serverKeyType": "AzureKeyVault" + } + ] + }, + "encryptionProtectorObj": { + "value": { + "serverKeyName": "adp-<>-az-kv-x-sqlmi_keyEncryptionKeySqlMi_4bf367f64c914d8ba698700fb598ad07", // ID must be updated for new keys + "serverKeyType": "AzureKeyVault" + } + }, + "securityAlertPoliciesObj": { + "value": { + "name": "default", + "state": "Enabled", + "emailAccountAdmins": true + } + }, + "vulnerabilityAssessmentsObj": { + "value": { + "name": "default", + "emailSubscriptionAdmins": true, + "recurringScansIsEnabled": true, + "recurringScansEmails": [ + "test1@contoso.com", + "test2@contoso.com" + ], + "vulnerabilityAssessmentsStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + }, + "databases": { + "value": [ + { + "name": "<>-az-sqlmidb-x-001", + "backupShortTermRetentionPolicies": { + "name": "default" + }, + "backupLongTermRetentionPolicies": { + "name": "default" + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/deploy.bicep new file mode 100644 index 000000000..50e79f8ed --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/deploy.bicep @@ -0,0 +1,53 @@ +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Required. Login name of the managed instance administrator.') +param login string + +@description('Required. SID (object ID) of the managed instance administrator.') +param sid string + +@description('Optional. The name of the managed instance administrator') +param name string = 'ActiveDirectory' + +@description('Optional. Tenant ID of the managed instance administrator.') +param tenantId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource administrator 'Microsoft.Sql/managedInstances/administrators@2021-02-01-preview' = { + name: name + parent: managedInstance + properties: { + administratorType: 'ActiveDirectory' + login: login + sid: sid + tenantId: tenantId + } +} + +@description('The name of the deployed managed instance') +output name string = administrator.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = administrator.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/readme.md new file mode 100644 index 000000000..54b9fac2e --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/readme.md @@ -0,0 +1,45 @@ +# SQL Managed Instances Administrator `[Microsoft.Sql/managedInstances/administrators]` + +This module deploys an administrator for the SQL managed instance + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/administrators` | 2021-02-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `login` | string | Login name of the managed instance administrator. | +| `managedInstanceName` | string | Name of the SQL managed instance. | +| `sid` | string | SID (object ID) of the managed instance administrator. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'ActiveDirectory'` | The name of the managed instance administrator | +| `tenantId` | string | `''` | Tenant ID of the managed instance administrator. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | + +## Template references + +- [Managedinstances/Administrators](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/administrators) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/administrators/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/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/deploy.bicep new file mode 100644 index 000000000..fe8d57289 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/deploy.bicep @@ -0,0 +1,63 @@ +@description('Required. The name of the Long Term Retention backup policy. For example "default".') +param name string + +@description('Required. The name of the managed instance database') +param databaseName string + +@description('Required. Name of the managed instance.') +param managedInstanceName string + +@description('Optional. The week of year to take the yearly backup in an ISO 8601 format.') +param weekOfYear int = 5 + +@description('Optional. The weekly retention policy for an LTR backup in an ISO 8601 format.') +param weeklyRetention string = 'P1M' + +@description('Optional. The monthly retention policy for an LTR backup in an ISO 8601 format.') +param monthlyRetention string = 'P1Y' + +@description('Optional. The yearly retention policy for an LTR backup in an ISO 8601 format.') +param yearlyRetention string = 'P5Y' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName + + resource managedInstaceDatabase 'databases@2020-02-02-preview' existing = { + name: databaseName + } +} + +resource backupLongTermRetentionPolicy 'Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies@2021-02-01-preview' = { + name: name + parent: managedInstance::managedInstaceDatabase + properties: { + monthlyRetention: monthlyRetention + weeklyRetention: weeklyRetention + weekOfYear: weekOfYear + yearlyRetention: yearlyRetention + } +} + +@description('The name of the deployed database backup long-term retention policy') +output name string = backupLongTermRetentionPolicy.name + +@description('The resource ID of the deployed database backup long-term retention policy') +output resourceId string = backupLongTermRetentionPolicy.id + +@description('The resource group of the deployed database backup long-term retention policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/readme.md new file mode 100644 index 000000000..950e2bbe7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/readme.md @@ -0,0 +1,47 @@ +# SQL Managed Instance Database Backup Long-Term Retention Policy `[Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies]` + +This module deploys a backup long-term retention policies for SQL Managed Instance databases + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies` | 2021-02-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `databaseName` | string | The name of the managed instance database | +| `managedInstanceName` | string | Name of the managed instance. | +| `name` | string | The name of the Long Term Retention backup policy. For example "default". | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `monthlyRetention` | string | `'P1Y'` | The monthly retention policy for an LTR backup in an ISO 8601 format. | +| `weeklyRetention` | string | `'P1M'` | The weekly retention policy for an LTR backup in an ISO 8601 format. | +| `weekOfYear` | int | `5` | The week of year to take the yearly backup in an ISO 8601 format. | +| `yearlyRetention` | string | `'P5Y'` | The yearly retention policy for an LTR backup in an ISO 8601 format. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database backup long-term retention policy | +| `resourceGroupName` | string | The resource group of the deployed database backup long-term retention policy | +| `resourceId` | string | The resource ID of the deployed database backup long-term retention policy | + +## Template references + +- [Managedinstances/Databases/Backuplongtermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/databases/backupLongTermRetentionPolicies) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies/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/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/deploy.bicep new file mode 100644 index 000000000..aeb359a9e --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. The name of the Short Term Retention backup policy. For example "default".') +param name string + +@description('Required. The name of the SQL managed instance database') +param databaseName string + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. The backup retention period in days. This is how many days Point-in-Time Restore will be supported.') +param retentionDays int = 35 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName + + resource managedInstaceDatabase 'databases@2020-02-02-preview' existing = { + name: databaseName + } +} + +resource backupShortTermRetentionPolicy 'Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies@2017-03-01-preview' = { + name: name + parent: managedInstance::managedInstaceDatabase + properties: { + retentionDays: retentionDays + } +} + +@description('The name of the deployed database backup short-term retention policy') +output name string = backupShortTermRetentionPolicy.name + +@description('The resource ID of the deployed database backup short-term retention policy') +output resourceId string = backupShortTermRetentionPolicy.id + +@description('The resource group of the deployed database backup short-term retention policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/readme.md new file mode 100644 index 000000000..286c73bb3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/readme.md @@ -0,0 +1,45 @@ +# SQL Managed Instance Database Backup Short-Term Retention Policy `[Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies]` + +This module deploys a backup short-term retention policies for SQL Managed Instance databases + + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies` | 2017-03-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `databaseName` | string | The name of the SQL managed instance database | +| `managedInstanceName` | string | Name of the SQL managed instance. | +| `name` | string | The name of the Short Term Retention backup policy. For example "default". | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `retentionDays` | int | `35` | The backup retention period in days. This is how many days Point-in-Time Restore will be supported. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database backup short-term retention policy | +| `resourceGroupName` | string | The resource group of the deployed database backup short-term retention policy | +| `resourceId` | string | The resource ID of the deployed database backup short-term retention policy | + +## Template references + +- [Managedinstances/Databases/Backupshorttermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/databases/backupShortTermRetentionPolicies) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies/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/carml/1.0.1/Microsoft.Sql/managedInstances/databases/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/deploy.bicep new file mode 100644 index 000000000..96935dc4e --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/deploy.bicep @@ -0,0 +1,196 @@ +@description('Required. The name of the SQL managed instance database.') +param name string + +@description('Required. The name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Collation of the managed instance database.') +param collation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. Conditional. If createMode is PointInTimeRestore, this value is required. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database.') +param restorePointInTime string = '' + +@description('Optional. Collation of the managed instance.') +param catalogCollation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. Managed database create mode. PointInTimeRestore: Create a database by restoring a point in time backup of an existing database. SourceDatabaseName, SourceManagedInstanceName and PointInTime must be specified. RestoreExternalBackup: Create a database by restoring from external backup files. Collation, StorageContainerUri and StorageContainerSasToken must be specified. Recovery: Creates a database by restoring a geo-replicated backup. RecoverableDatabaseId must be specified as the recoverable database resource ID to restore.') +@allowed([ + 'Default' + 'RestoreExternalBackup' + 'PointInTimeRestore' + 'Recovery' + 'RestoreLongTermRetentionBackup' +]) +param createMode string = 'Default' + +@description('Optional. Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the uri of the storage container where backups for this restore are stored.') +param storageContainerUri string = '' + +@description('Optional. Conditional. The resource identifier of the source database associated with create operation of this database.') +param sourceDatabaseId string = '' + +@description('Optional. Conditional. The restorable dropped database resource ID to restore when creating this database.') +param restorableDroppedDatabaseId string = '' + +@description('Optional. Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the storage container sas token.') +param storageContainerSasToken string = '' + +@description('Optional. Conditional. The resource identifier of the recoverable database associated with create operation of this database.') +param recoverableDatabaseId string = '' + +@description('Optional. Conditional. The name of the Long Term Retention backup to be used for restore of this managed database.') +param longTermRetentionBackupResourceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. The configuration for the backup short term retention policy definition') +param backupShortTermRetentionPoliciesObj object = {} + +@description('Optional. The configuration for the backup long term retention policy definition') +param backupLongTermRetentionPoliciesObj object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'SQLInsights' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' +]) +param diagnosticLogCategoriesToEnable array = [ + 'SQLInsights' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource database 'Microsoft.Sql/managedInstances/databases@2021-05-01-preview' = { + name: name + parent: managedInstance + location: location + tags: tags + properties: { + collation: empty(collation) ? null : collation + restorePointInTime: empty(restorePointInTime) ? null : restorePointInTime + catalogCollation: empty(catalogCollation) ? null : catalogCollation + createMode: empty(createMode) ? null : createMode + storageContainerUri: empty(storageContainerUri) ? null : storageContainerUri + sourceDatabaseId: empty(sourceDatabaseId) ? null : sourceDatabaseId + restorableDroppedDatabaseId: empty(restorableDroppedDatabaseId) ? null : restorableDroppedDatabaseId + storageContainerSasToken: empty(storageContainerSasToken) ? null : storageContainerSasToken + recoverableDatabaseId: empty(recoverableDatabaseId) ? null : recoverableDatabaseId + longTermRetentionBackupResourceId: empty(longTermRetentionBackupResourceId) ? null : longTermRetentionBackupResourceId + } +} + +resource database_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${last(split(database.name, '/'))}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: database +} + +resource database_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: database +} + +module database_backupShortTermRetentionPolicy 'backupShortTermRetentionPolicies/deploy.bicep' = if (!empty(backupShortTermRetentionPoliciesObj)) { + name: '${deployment().name}-BackupShortTRetPol' + params: { + managedInstanceName: managedInstanceName + databaseName: last(split(database.name, '/')) + name: backupShortTermRetentionPoliciesObj.name + retentionDays: contains(backupShortTermRetentionPoliciesObj, 'retentionDays') ? backupShortTermRetentionPoliciesObj.retentionDays : 35 + } +} + +module database_backupLongTermRetentionPolicy 'backupLongTermRetentionPolicies/deploy.bicep' = if (!empty(backupLongTermRetentionPoliciesObj)) { + name: '${deployment().name}-BackupLongTRetPol' + params: { + managedInstanceName: managedInstanceName + databaseName: last(split(database.name, '/')) + name: backupLongTermRetentionPoliciesObj.name + weekOfYear: contains(backupLongTermRetentionPoliciesObj, 'weekOfYear') ? backupLongTermRetentionPoliciesObj.weekOfYear : 5 + weeklyRetention: contains(backupLongTermRetentionPoliciesObj, 'weeklyRetention') ? backupLongTermRetentionPoliciesObj.weeklyRetention : 'P1M' + monthlyRetention: contains(backupLongTermRetentionPoliciesObj, 'monthlyRetention') ? backupLongTermRetentionPoliciesObj.monthlyRetention : 'P1Y' + yearlyRetention: contains(backupLongTermRetentionPoliciesObj, 'yearlyRetention') ? backupLongTermRetentionPoliciesObj.yearlyRetention : 'P5Y' + } +} + +@description('The name of the deployed database') +output name string = database.name + +@description('The resource ID of the deployed database') +output resourceId string = database.id + +@description('The resource group the database was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/databases/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/readme.md new file mode 100644 index 000000000..dda0f1e01 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/readme.md @@ -0,0 +1,93 @@ +# SQL Managed Instances Database `[Microsoft.Sql/managedInstances/databases]` + +This template deploys a SQL Managed Instances Database. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/databases` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies` | 2021-02-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies` | 2017-03-01-preview | + +### Deployment prerequisites + +The SQL Managed Instance Database is deployed on a SQL Managed Instance. + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `managedInstanceName` | string | The name of the SQL managed instance. | +| `name` | string | The name of the SQL managed instance database. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backupLongTermRetentionPoliciesObj` | _[backupLongTermRetentionPolicies](backupLongTermRetentionPolicies/readme.md)_ object | `{object}` | | The configuration for the backup long term retention policy definition | +| `backupShortTermRetentionPoliciesObj` | _[backupShortTermRetentionPolicies](backupShortTermRetentionPolicies/readme.md)_ object | `{object}` | | The configuration for the backup short term retention policy definition | +| `catalogCollation` | string | `'SQL_Latin1_General_CP1_CI_AS'` | | Collation of the managed instance. | +| `collation` | string | `'SQL_Latin1_General_CP1_CI_AS'` | | Collation of the managed instance database. | +| `createMode` | string | `'Default'` | `[Default, RestoreExternalBackup, PointInTimeRestore, Recovery, RestoreLongTermRetentionBackup]` | Managed database create mode. PointInTimeRestore: Create a database by restoring a point in time backup of an existing database. SourceDatabaseName, SourceManagedInstanceName and PointInTime must be specified. RestoreExternalBackup: Create a database by restoring from external backup files. Collation, StorageContainerUri and StorageContainerSasToken must be specified. Recovery: Creates a database by restoring a geo-replicated backup. RecoverableDatabaseId must be specified as the recoverable database resource ID to restore. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[SQLInsights, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors]` | `[SQLInsights, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `longTermRetentionBackupResourceId` | string | `''` | | Conditional. The name of the Long Term Retention backup to be used for restore of this managed database. | +| `recoverableDatabaseId` | string | `''` | | Conditional. The resource identifier of the recoverable database associated with create operation of this database. | +| `restorableDroppedDatabaseId` | string | `''` | | Conditional. The restorable dropped database resource ID to restore when creating this database. | +| `restorePointInTime` | string | `''` | | Conditional. If createMode is PointInTimeRestore, this value is required. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. | +| `sourceDatabaseId` | string | `''` | | Conditional. The resource identifier of the source database associated with create operation of this database. | +| `storageContainerSasToken` | string | `''` | | Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the storage container sas token. | +| `storageContainerUri` | string | `''` | | Conditional. If createMode is RestoreExternalBackup, this value is required. Specifies the uri of the storage container where backups for this restore are stored. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database | +| `resourceGroupName` | string | The resource group the database was deployed into | +| `resourceId` | string | The resource ID of the deployed database | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Managedinstances/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/databases) +- [Managedinstances/Databases/Backuplongtermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/databases/backupLongTermRetentionPolicies) +- [Managedinstances/Databases/Backupshorttermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/databases/backupShortTermRetentionPolicies) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/databases/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/databases/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/carml/1.0.1/Microsoft.Sql/managedInstances/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/deploy.bicep new file mode 100644 index 000000000..7e101509f --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/deploy.bicep @@ -0,0 +1,376 @@ +@description('Required. The name of the SQL managed instance.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The username used to establish jumpbox VMs.') +param administratorLogin string + +@description('Required. The password given to the admin user.') +@secure() +param administratorLoginPassword string + +@description('Required. The fully qualified resource ID of the subnet on which the SQL managed instance will be placed.') +param subnetId string + +@description('Optional. The name of the SKU, typically, a letter + Number code, e.g. P3.') +param skuName string = 'GP_Gen5' + +@description('Optional. The tier or edition of the particular SKU, e.g. Basic, Premium.') +param skuTier string = 'GeneralPurpose' + +@description('Optional. Storage size in GB. Minimum value: 32. Maximum value: 8192. Increments of 32 GB allowed only.') +param storageSizeInGB int = 32 + +@description('Optional. The number of vCores. Allowed values: 8, 16, 24, 32, 40, 64, 80.') +param vCores int = 4 + +@description('Optional. The license type. Possible values are \'LicenseIncluded\' (regular price inclusive of a new SQL license) and \'BasePrice\' (discounted AHB price for bringing your own SQL licenses).') +@allowed([ + 'LicenseIncluded' + 'BasePrice' +]) +param licenseType string = 'LicenseIncluded' + +@description('Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here.') +param hardwareFamily string = 'Gen5' + +@description('Optional. Whether or not multi-az is enabled.') +param zoneRedundant bool = false + +@description('Optional. Service principal type. If using AD Authentication and applying Admin, must be set to `SystemAssigned`. Then Global Admin must allow Reader access to Azure AD for the Service Principal') +@allowed([ + 'None' + 'SystemAssigned' +]) +param servicePrincipal string = 'None' + +@description('Optional. Specifies the mode of database creation. Default: Regular instance creation. Restore: Creates an instance by restoring a set of backups to specific point in time. RestorePointInTime and SourceManagedInstanceId must be specified.') +@allowed([ + 'Default' + 'PointInTimeRestore' +]) +param managedInstanceCreateMode string = 'Default' + +@description('Optional. The resource ID of another managed instance whose DNS zone this managed instance will share after creation.') +param dnsZonePartner string = '' + +@description('Optional. Collation of the managed instance.') +param collation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. Connection type used for connecting to the instance.') +@allowed([ + 'Proxy' + 'Redirect' + 'Default' +]) +param proxyOverride string = 'Proxy' + +@description('Optional. Whether or not the public data endpoint is enabled.') +param publicDataEndpointEnabled bool = false + +@description('Optional. ID of the timezone. Allowed values are timezones supported by Windows.') +param timezoneId string = 'UTC' + +@description('Optional. The resource ID of the instance pool this managed server belongs to.') +param instancePoolResourceId string = '' + +@description('Optional. Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database.') +param restorePointInTime string = '' + +@description('Optional. The resource identifier of the source managed instance associated with create operation of this instance.') +param sourceManagedInstanceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Mandatory if "managedServiceIdentity" contains UserAssigned. The resource ID of a user assigned identity to be used by default.') +param primaryUserAssignedIdentityId string = '' + +@description('Optional. Databases to create in this server.') +param databases array = [] + +@description('Optional. The vulnerability assessment configuration') +param vulnerabilityAssessmentsObj object = {} + +@description('Optional. The security alert policy configuration') +param securityAlertPoliciesObj object = {} + +@description('Optional. The keys to configure') +param keys array = [] + +@description('Optional. The encryption protection configuration') +param encryptionProtectorObj object = {} + +@description('Optional. The administrator configuration') +param administratorsObj object = {} + +@description('Optional. The storage account type used to store backups for this database.') +@allowed([ + 'Geo' + 'GeoZone' + 'Local' + 'Zone' +]) +param requestedBackupStorageRedundancy string = 'Geo' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ResourceUsageStats' + 'SQLSecurityAuditEvents' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ResourceUsageStats' + 'SQLSecurityAuditEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' = { + name: name + location: location + identity: identity + sku: { + name: skuName + tier: skuTier + family: hardwareFamily + } + tags: tags + properties: { + managedInstanceCreateMode: managedInstanceCreateMode + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword + subnetId: subnetId + licenseType: licenseType + vCores: vCores + storageSizeInGB: storageSizeInGB + collation: collation + dnsZonePartner: dnsZonePartner + publicDataEndpointEnabled: publicDataEndpointEnabled + sourceManagedInstanceId: sourceManagedInstanceId + restorePointInTime: restorePointInTime + proxyOverride: proxyOverride + timezoneId: timezoneId + instancePoolId: instancePoolResourceId + primaryUserAssignedIdentityId: primaryUserAssignedIdentityId + requestedBackupStorageRedundancy: requestedBackupStorageRedundancy + zoneRedundant: zoneRedundant + servicePrincipal: { + type: servicePrincipal + } + } +} + +resource managedInstance_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${managedInstance.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: managedInstance +} + +resource managedInstance_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: managedInstance +} + +module managedInstance_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-SqlMi-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: managedInstance.id + } +}] + +module managedInstance_databases 'databases/deploy.bicep' = [for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-SqlMi-DB-${index}' + params: { + name: database.name + managedInstanceName: managedInstance.name + catalogCollation: contains(database, 'catalogCollation') ? database.catalogCollation : 'SQL_Latin1_General_CP1_CI_AS' + collation: contains(database, 'collation') ? database.collation : 'SQL_Latin1_General_CP1_CI_AS' + createMode: contains(database, 'createMode') ? database.createMode : 'Default' + diagnosticLogsRetentionInDays: contains(database, 'diagnosticLogsRetentionInDays') ? database.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(database, 'diagnosticStorageAccountId') ? database.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(database, 'diagnosticEventHubAuthorizationRuleId') ? database.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(database, 'diagnosticEventHubName') ? database.diagnosticEventHubName : '' + location: contains(database, 'location') ? database.location : managedInstance.location + lock: contains(database, 'lock') ? database.lock : lock + longTermRetentionBackupResourceId: contains(database, 'longTermRetentionBackupResourceId') ? database.longTermRetentionBackupResourceId : '' + recoverableDatabaseId: contains(database, 'recoverableDatabaseId') ? database.recoverableDatabaseId : '' + restorableDroppedDatabaseId: contains(database, 'restorableDroppedDatabaseId') ? database.restorableDroppedDatabaseId : '' + restorePointInTime: contains(database, 'restorePointInTime') ? database.restorePointInTime : '' + sourceDatabaseId: contains(database, 'sourceDatabaseId') ? database.sourceDatabaseId : '' + storageContainerSasToken: contains(database, 'storageContainerSasToken') ? database.storageContainerSasToken : '' + storageContainerUri: contains(database, 'storageContainerUri') ? database.storageContainerUri : '' + tags: contains(database, 'tags') ? database.tags : {} + diagnosticWorkspaceId: contains(database, 'diagnosticWorkspaceId') ? database.diagnosticWorkspaceId : '' + backupShortTermRetentionPoliciesObj: contains(database, 'backupShortTermRetentionPolicies') ? database.backupShortTermRetentionPolicies : {} + backupLongTermRetentionPoliciesObj: contains(database, 'backupLongTermRetentionPolicies') ? database.backupLongTermRetentionPolicies : {} + } +}] + +module managedInstance_securityAlertPolicy 'securityAlertPolicies/deploy.bicep' = if (!empty(securityAlertPoliciesObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-SecAlertPol' + params: { + managedInstanceName: managedInstance.name + name: securityAlertPoliciesObj.name + emailAccountAdmins: contains(securityAlertPoliciesObj, 'emailAccountAdmins') ? securityAlertPoliciesObj.emailAccountAdmins : false + state: contains(securityAlertPoliciesObj, 'state') ? securityAlertPoliciesObj.state : 'Disabled' + } +} + +module managedInstance_vulnerabilityAssessment 'vulnerabilityAssessments/deploy.bicep' = if (!empty(vulnerabilityAssessmentsObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-VulnAssessm' + params: { + managedInstanceName: managedInstance.name + name: vulnerabilityAssessmentsObj.name + recurringScansEmails: contains(vulnerabilityAssessmentsObj, 'recurringScansEmails') ? vulnerabilityAssessmentsObj.recurringScansEmails : [] + recurringScansEmailSubscriptionAdmins: contains(vulnerabilityAssessmentsObj, 'recurringScansEmailSubscriptionAdmins') ? vulnerabilityAssessmentsObj.recurringScansEmailSubscriptionAdmins : false + recurringScansIsEnabled: contains(vulnerabilityAssessmentsObj, 'recurringScansIsEnabled') ? vulnerabilityAssessmentsObj.recurringScansIsEnabled : false + vulnerabilityAssessmentsStorageAccountId: contains(vulnerabilityAssessmentsObj, 'vulnerabilityAssessmentsStorageAccountId') ? vulnerabilityAssessmentsObj.vulnerabilityAssessmentsStorageAccountId : '' + } + dependsOn: [ + managedInstance_securityAlertPolicy + ] +} + +module managedInstance_key 'keys/deploy.bicep' = [for (key, index) in keys: { + name: '${uniqueString(deployment().name, location)}-SqlMi-Key-${index}' + params: { + managedInstanceName: managedInstance.name + name: contains(key, 'name') ? key.name : '' + serverKeyType: contains(key, 'serverKeyType') ? key.serverKeyType : 'ServiceManaged' + uri: contains(key, 'uri') ? key.uri : '' + } +}] + +module managedInstance_encryptionProtector 'encryptionProtector/deploy.bicep' = if (!empty(encryptionProtectorObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-EncryProtector' + params: { + managedInstanceName: managedInstance.name + serverKeyName: contains(encryptionProtectorObj, 'serverKeyName') ? encryptionProtectorObj.serverKeyName : managedInstance_key[0].outputs.name + name: contains(encryptionProtectorObj, 'name') ? encryptionProtectorObj.serverKeyType : 'current' + serverKeyType: contains(encryptionProtectorObj, 'serverKeyType') ? encryptionProtectorObj.serverKeyType : 'ServiceManaged' + autoRotationEnabled: contains(encryptionProtectorObj, 'autoRotationEnabled') ? encryptionProtectorObj.autoRotationEnabled : true + } +} + +module managedInstance_administrator 'administrators/deploy.bicep' = if (!empty(administratorsObj)) { + name: '${uniqueString(deployment().name, location)}-SqlMi-Admin' + params: { + managedInstanceName: managedInstance.name + login: administratorsObj.name + sid: administratorsObj.sid + tenantId: contains(administratorsObj, 'tenantId') ? administratorsObj.tenantId : '' + } +} + +@description('The name of the deployed managed instance') +output name string = managedInstance.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = managedInstance.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(managedInstance.identity, 'principalId') ? managedInstance.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/deploy.bicep new file mode 100644 index 000000000..d22b47598 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. The name of the encryptionProtector') +param name string = 'current' + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Required. The name of the SQL managed instance key.') +param serverKeyName string + +@description('Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault".') +@allowed([ + 'AzureKeyVault' + 'ServiceManaged' +]) +param serverKeyType string = 'ServiceManaged' + +@description('Optional. Key auto rotation opt-in flag') +param autoRotationEnabled bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource encryptionProtector 'Microsoft.Sql/managedInstances/encryptionProtector@2021-05-01-preview' = { + name: name + parent: managedInstance + properties: { + autoRotationEnabled: autoRotationEnabled + serverKeyName: serverKeyName + serverKeyType: serverKeyType + } +} + +@description('The name of the deployed managed instance') +output name string = encryptionProtector.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = encryptionProtector.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/readme.md new file mode 100644 index 000000000..13e5e63f7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/readme.md @@ -0,0 +1,45 @@ +# SQL Managed Instance Encryption Protector `[Microsoft.Sql/managedInstances/encryptionProtector]` + +This module deploys an encryption protector for a SQL managed instance. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/encryptionProtector` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `managedInstanceName` | string | | Name of the SQL managed instance. | +| `name` | string | `'current'` | The name of the encryptionProtector | +| `serverKeyName` | string | | The name of the SQL managed instance key. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `autoRotationEnabled` | bool | `False` | | Key auto rotation opt-in flag | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `serverKeyType` | string | `'ServiceManaged'` | `[AzureKeyVault, ServiceManaged]` | The encryption protector type like "ServiceManaged", "AzureKeyVault". | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | + +## Template references + +- [Managedinstances/Encryptionprotector](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/encryptionProtector) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/encryptionProtector/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/carml/1.0.1/Microsoft.Sql/managedInstances/keys/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/keys/deploy.bicep new file mode 100644 index 000000000..6249ba56a --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/keys/deploy.bicep @@ -0,0 +1,58 @@ +@description('Optional. The name of the key. Must follow the [__] pattern') +param name string = '' + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. The encryption protector type like "ServiceManaged", "AzureKeyVault"') +@allowed([ + 'AzureKeyVault' + 'ServiceManaged' +]) +param serverKeyType string = 'ServiceManaged' + +@description('Optional. The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required.') +param uri string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var splittedKeyUri = split(uri, '/') + +// if serverManaged, use serverManaged, if uri provided use concated uri value +// MUST match the pattern '__' +var serverKeyName = empty(uri) ? 'ServiceManaged' : '${split(splittedKeyUri[2], '.')[0]}_${splittedKeyUri[4]}_${splittedKeyUri[5]}' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource key 'Microsoft.Sql/managedInstances/keys@2021-05-01-preview' = { + name: !empty(name) ? name : serverKeyName + parent: managedInstance + properties: { + serverKeyType: serverKeyType + uri: uri + } +} + +@description('The name of the deployed managed instance') +output name string = key.name + +@description('The resource ID of the deployed managed instance') +output resourceId string = key.id + +@description('The resource group of the deployed managed instance') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/keys/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/keys/readme.md new file mode 100644 index 000000000..e70e7ac39 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/keys/readme.md @@ -0,0 +1,44 @@ +# SQL Managed Instance Keys `[Microsoft.Sql/managedInstances/keys]` + +This module deploys a key for a SQL managed instance. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/keys` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `managedInstanceName` | string | Name of the SQL managed instance. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `''` | | The name of the key. Must follow the [__] pattern | +| `serverKeyType` | string | `'ServiceManaged'` | `[AzureKeyVault, ServiceManaged]` | The encryption protector type like "ServiceManaged", "AzureKeyVault" | +| `uri` | string | `''` | | The URI of the key. If the ServerKeyType is AzureKeyVault, then either the URI or the keyVaultName/keyName combination is required. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | + +## Template references + +- [Managedinstances/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/keys) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/keys/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/keys/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/keys/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/carml/1.0.1/Microsoft.Sql/managedInstances/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/readme.md new file mode 100644 index 000000000..1f98b8342 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/readme.md @@ -0,0 +1,185 @@ +# SQL Managed Instances `[Microsoft.Sql/managedInstances]` + +This template deploys a SQL managed instance. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/administrators` | 2021-02-01-preview | +| `Microsoft.Sql/managedInstances/databases` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupLongTermRetentionPolicies` | 2021-02-01-preview | +| `Microsoft.Sql/managedInstances/databases/backupShortTermRetentionPolicies` | 2017-03-01-preview | +| `Microsoft.Sql/managedInstances/encryptionProtector` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/keys` | 2021-05-01-preview | +| `Microsoft.Sql/managedInstances/securityAlertPolicies` | 2017-03-01-preview | +| `Microsoft.Sql/managedInstances/vulnerabilityAssessments` | 2021-02-01-preview | + +### Deployment prerequisites + +#### Networking + +SQL Managed Instance is deployed on a virtual network to a subnet that is delagated to the SQL MI service. This network is required to satisfy the requirements explained [here](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-managed-instance-connectivity-architecture#network-requirements). + +SQL MI requires that the subnet have a Route Table and NSG assigned to it. The SQL MI service will automatically add Routes to the Route Table and Rules to the NSG once the SQL MI has been deployed. As a result, the parameter file for the Route Table and NSG will have to be updated afterwards with the created Routes & Rules, otherwise redeployment of the Route Table & NSG via Bicep/ARM will fail. + +#### Azure AD Authentication + +SQL MI allows for Azure AD Authentication via an [Azure AD Admin](https://docs.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure?tabs=azure-powershell#provision-azure-ad-admin-sql-managed-instance). This requires a Service Principal to be assigned and granted Reader rights to Azure AD by an AD Admin. To do so via this module, the `servicePrincipal` parameter must be set to `SystemAssigned` and deploy the SQL MI. Afterwards an Azure AD Admin must go to the SQL MI Azure Active Directory admin page in the Azure Portal and assigned the Reader rights. Next the `administratorsObj` must be configured in the parameter file and be redeployed. + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `administratorLogin` | string | The username used to establish jumpbox VMs. | +| `administratorLoginPassword` | secureString | The password given to the admin user. | +| `name` | string | The name of the SQL managed instance. | +| `subnetId` | string | The fully qualified resource ID of the subnet on which the SQL managed instance will be placed. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `administratorsObj` | _[administrators](administrators/readme.md)_ object | `{object}` | | The administrator configuration | +| `collation` | string | `'SQL_Latin1_General_CP1_CI_AS'` | | Collation of the managed instance. | +| `databases` | _[databases](databases/readme.md)_ array | `[]` | | Databases to create in this server. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ResourceUsageStats, SQLSecurityAuditEvents]` | `[ResourceUsageStats, SQLSecurityAuditEvents]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `dnsZonePartner` | string | `''` | | The resource ID of another managed instance whose DNS zone this managed instance will share after creation. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `encryptionProtectorObj` | _[encryptionProtector](encryptionProtector/readme.md)_ object | `{object}` | | The encryption protection configuration | +| `hardwareFamily` | string | `'Gen5'` | | If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| `instancePoolResourceId` | string | `''` | | The resource ID of the instance pool this managed server belongs to. | +| `keys` | _[keys](keys/readme.md)_ array | `[]` | | The keys to configure | +| `licenseType` | string | `'LicenseIncluded'` | `[LicenseIncluded, BasePrice]` | The license type. Possible values are 'LicenseIncluded' (regular price inclusive of a new SQL license) and 'BasePrice' (discounted AHB price for bringing your own SQL licenses). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managedInstanceCreateMode` | string | `'Default'` | `[Default, PointInTimeRestore]` | Specifies the mode of database creation. Default: Regular instance creation. Restore: Creates an instance by restoring a set of backups to specific point in time. RestorePointInTime and SourceManagedInstanceId must be specified. | +| `primaryUserAssignedIdentityId` | string | `''` | | Mandatory if "managedServiceIdentity" contains UserAssigned. The resource ID of a user assigned identity to be used by default. | +| `proxyOverride` | string | `'Proxy'` | `[Proxy, Redirect, Default]` | Connection type used for connecting to the instance. | +| `publicDataEndpointEnabled` | bool | `False` | | Whether or not the public data endpoint is enabled. | +| `requestedBackupStorageRedundancy` | string | `'Geo'` | `[Geo, GeoZone, Local, Zone]` | The storage account type used to store backups for this database. | +| `restorePointInTime` | string | `''` | | Specifies the point in time (ISO8601 format) of the source database that will be restored to create the new database. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityAlertPoliciesObj` | _[securityAlertPolicies](securityAlertPolicies/readme.md)_ object | `{object}` | | The security alert policy configuration | +| `servicePrincipal` | string | `'None'` | `[None, SystemAssigned]` | Service principal type. If using AD Authentication and applying Admin, must be set to `SystemAssigned`. Then Global Admin must allow Reader access to Azure AD for the Service Principal | +| `skuName` | string | `'GP_Gen5'` | | The name of the SKU, typically, a letter + Number code, e.g. P3. | +| `skuTier` | string | `'GeneralPurpose'` | | The tier or edition of the particular SKU, e.g. Basic, Premium. | +| `sourceManagedInstanceId` | string | `''` | | The resource identifier of the source managed instance associated with create operation of this instance. | +| `storageSizeInGB` | int | `32` | | Storage size in GB. Minimum value: 32. Maximum value: 8192. Increments of 32 GB allowed only. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timezoneId` | string | `'UTC'` | | ID of the timezone. Allowed values are timezones supported by Windows. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vCores` | int | `4` | | The number of vCores. Allowed values: 8, 16, 24, 32, 40, 64, 80. | +| `vulnerabilityAssessmentsObj` | _[vulnerabilityAssessments](vulnerabilityAssessments/readme.md)_ object | `{object}` | | The vulnerability assessment configuration | +| `zoneRedundant` | bool | `False` | | Whether or not multi-az is enabled. | + + +### Parameter Usage : `userAssignedIdentities` + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed managed instance | +| `resourceGroupName` | string | The resource group of the deployed managed instance | +| `resourceId` | string | The resource ID of the deployed managed instance | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Managedinstances](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances) +- [Managedinstances/Administrators](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/administrators) +- [Managedinstances/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/databases) +- [Managedinstances/Databases/Backuplongtermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/databases/backupLongTermRetentionPolicies) +- [Managedinstances/Databases/Backupshorttermretentionpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/databases/backupShortTermRetentionPolicies) +- [Managedinstances/Encryptionprotector](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/encryptionProtector) +- [Managedinstances/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/managedInstances/keys) +- [Managedinstances/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/securityAlertPolicies) +- [Managedinstances/Vulnerabilityassessments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/vulnerabilityAssessments) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/deploy.bicep new file mode 100644 index 000000000..f38e1c448 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. The name of the security alert policy') +param name string + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. Enables advanced data security features, like recuring vulnerability assesment scans and ATP. If enabled, storage account must be provided.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param state string = 'Disabled' + +@description('Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators.') +param emailAccountAdmins bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource securityAlertPolicy 'Microsoft.Sql/managedInstances/securityAlertPolicies@2017-03-01-preview' = { + name: name + parent: managedInstance + properties: { + state: state + emailAccountAdmins: emailAccountAdmins + } +} + +@description('The name of the deployed security alert policy') +output name string = securityAlertPolicy.name + +@description('The resource ID of the deployed security alert policy') +output resourceId string = securityAlertPolicy.id + +@description('The resource group of the deployed security alert policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/readme.md new file mode 100644 index 000000000..a99f278e3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/readme.md @@ -0,0 +1,44 @@ +# SQL Managed Instance Security Alert Policy `[Microsoft.Sql/managedInstances/securityAlertPolicies]` + +This module deploys a security alert policy for a SQL managed instance. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/securityAlertPolicies` | 2017-03-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `managedInstanceName` | string | Name of the SQL managed instance. | +| `name` | string | The name of the security alert policy | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `emailAccountAdmins` | bool | `False` | | Specifies that the schedule scan notification will be is sent to the subscription administrators. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `state` | string | `'Disabled'` | `[Enabled, Disabled]` | Enables advanced data security features, like recuring vulnerability assesment scans and ATP. If enabled, storage account must be provided. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed security alert policy | +| `resourceGroupName` | string | The resource group of the deployed security alert policy | +| `resourceId` | string | The resource ID of the deployed security alert policy | + +## Template references + +- [Managedinstances/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2017-03-01-preview/managedInstances/securityAlertPolicies) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/securityAlertPolicies/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/carml/1.0.1/Microsoft.Sql/managedInstances/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/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/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/deploy.bicep b/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/deploy.bicep new file mode 100644 index 000000000..45c211f29 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/deploy.bicep @@ -0,0 +1,59 @@ +@description('Required. The name of the vulnerability assessment') +param name string + +@description('Required. Name of the SQL managed instance.') +param managedInstanceName string + +@description('Optional. Recurring scans state.') +param recurringScansIsEnabled bool = false + +@description('Optional. Specifies that the schedule scan notification will be is sent to the subscription administrators.') +param recurringScansEmailSubscriptionAdmins bool = false + +@description('Optional. Specifies an array of email addresses to which the scan notification is sent.') +param recurringScansEmails array = [] + +@description('Optional. A blob storage to hold the scan results.') +param vulnerabilityAssessmentsStorageAccountId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource managedInstance 'Microsoft.Sql/managedInstances@2021-05-01-preview' existing = { + name: managedInstanceName +} + +resource vulnerabilityAssessment 'Microsoft.Sql/managedInstances/vulnerabilityAssessments@2021-02-01-preview' = { + name: name + parent: managedInstance + properties: { + storageContainerPath: 'https://${last(split(vulnerabilityAssessmentsStorageAccountId, '/'))}.blob.${environment().suffixes.storage}/vulnerability-assessment/' + storageAccountAccessKey: listKeys(vulnerabilityAssessmentsStorageAccountId, '2019-06-01').keys[0].value + recurringScans: { + isEnabled: recurringScansIsEnabled + emailSubscriptionAdmins: recurringScansEmailSubscriptionAdmins + emails: recurringScansEmails + } + } +} + +@description('The name of the deployed vulnerability assessment') +output name string = vulnerabilityAssessment.name + +@description('The resource ID of the deployed vulnerability assessment') +output resourceId string = vulnerabilityAssessment.id + +@description('The resource group of the deployed vulnerability assessment') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/readme.md b/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/readme.md new file mode 100644 index 000000000..3bb5c7859 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/readme.md @@ -0,0 +1,46 @@ +# SQL Managed Instance Vulnerability Assessments `[Microsoft.Sql/managedInstances/vulnerabilityAssessments]` + +This module deploys a vulnerability assessment for a SQL managed instance. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/managedInstances/vulnerabilityAssessments` | 2021-02-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `managedInstanceName` | string | Name of the SQL managed instance. | +| `name` | string | The name of the vulnerability assessment | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `recurringScansEmails` | array | `[]` | Specifies an array of email addresses to which the scan notification is sent. | +| `recurringScansEmailSubscriptionAdmins` | bool | `False` | Specifies that the schedule scan notification will be is sent to the subscription administrators. | +| `recurringScansIsEnabled` | bool | `False` | Recurring scans state. | +| `vulnerabilityAssessmentsStorageAccountId` | string | `''` | A blob storage to hold the scan results. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed vulnerability assessment | +| `resourceGroupName` | string | The resource group of the deployed vulnerability assessment | +| `resourceId` | string | The resource ID of the deployed vulnerability assessment | + +## Template references + +- [Managedinstances/Vulnerabilityassessments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/managedInstances/vulnerabilityAssessments) diff --git a/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/version.json b/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/managedInstances/vulnerabilityAssessments/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/carml/1.0.1/Microsoft.Sql/servers/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Sql/servers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..58481cf64 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'SQL Server Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource server 'Microsoft.Sql/servers@2020-02-02-preview' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(server.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: server +}] diff --git a/carml/1.0.1/Microsoft.Sql/servers/.parameters/admin.parameters.json b/carml/1.0.1/Microsoft.Sql/servers/.parameters/admin.parameters.json new file mode 100644 index 000000000..eadb38dee --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/.parameters/admin.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": "<>-az-sqlsrv-admin-001" + }, + "administrators": { + "value": { + "azureADOnlyAuthentication": true, + "login": "myspn", + "sid": "<>", + "principalType": "Application", + "tenantId": "<>" + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Sql/servers/.parameters/parameters.json b/carml/1.0.1/Microsoft.Sql/servers/.parameters/parameters.json new file mode 100644 index 000000000..2c5e6acb9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/.parameters/parameters.json @@ -0,0 +1,83 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-sqlsrv-x-001" + }, + "administratorLogin": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/<>/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLogin" + } + }, + "administratorLoginPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/<>/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "administratorLoginPassword" + } + }, + "location": { + "value": "westeurope" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "databases": { + "value": [ + { + "name": "<>-az-sqldb-x-001", + "collation": "SQL_Latin1_General_CP1_CI_AS", + "skuTier": "BusinessCritical", + "skuName": "BC_Gen5", + "skuCapacity": 12, + "skuFamily": "Gen5", + "maxSizeBytes": 34359738368, + "licenseType": "LicenseIncluded", + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001" + } + ] + }, + "firewallRules": { + "value": [ + { + "name": "AllowAllWindowsAzureIps", + "endIpAddress": "0.0.0.0", + "startIpAddress": "0.0.0.0" + } + ] + }, + "securityAlertPolicies": { + "value": [ + { + "name": "Default", + "state": "Enabled", + "emailAccountAdmins": true + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Sql/servers/databases/deploy.bicep b/carml/1.0.1/Microsoft.Sql/servers/databases/deploy.bicep new file mode 100644 index 000000000..75b98cc14 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/databases/deploy.bicep @@ -0,0 +1,227 @@ +@description('Required. The name of the database.') +param name string + +@description('Required. The Name of SQL Server') +param serverName string + +@description('Optional. The collation of the database.') +param collation string = 'SQL_Latin1_General_CP1_CI_AS' + +@description('Optional. The skuTier or edition of the particular SKU.') +param skuTier string = 'GeneralPurpose' + +@description('Optional. The name of the SKU.') +param skuName string = 'GP_Gen5_2' + +@description('Optional. Capacity of the particular SKU.') +param skuCapacity int = -1 + +@description('Optional. If the service has different generations of hardware, for the same SKU, then that can be captured here.') +param skuFamily string = '' + +@description('Optional. Size of the particular SKU.') +param skuSize string = '' + +@description('Optional. The max size of the database expressed in bytes.') +param maxSizeBytes int = 34359738368 + +@description('Optional. The name of the sample schema to apply when creating this database.') +param sampleName string = '' + +@description('Optional. Whether or not this database is zone redundant.') +param zoneRedundant bool = false + +@description('Optional. The license type to apply for this database.') +param licenseType string = '' + +@description('Optional. The state of read-only routing.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param readScale string = 'Disabled' + +@description('Optional. The number of readonly secondary replicas associated with the database.') +param highAvailabilityReplicaCount int = 0 + +@description('Optional. Minimal capacity that database will always have allocated.') +param minCapacity string = '' + +@description('Optional. Time in minutes after which database is automatically paused.') +param autoPauseDelay string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'SQLInsights' + 'AutomaticTuning' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' + 'DatabaseWaitStatistics' + 'Timeouts' + 'Blocks' + 'Deadlocks' + 'DevOpsOperationsAudit' + 'SQLSecurityAuditEvents' +]) +param diagnosticLogCategoriesToEnable array = [ + 'SQLInsights' + 'AutomaticTuning' + 'QueryStoreRuntimeStatistics' + 'QueryStoreWaitStatistics' + 'Errors' + 'DatabaseWaitStatistics' + 'Timeouts' + 'Blocks' + 'Deadlocks' + 'DevOpsOperationsAudit' + 'SQLSecurityAuditEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Basic' + 'InstanceAndAppAdvanced' + 'WorkloadManagement' +]) +param diagnosticMetricsToEnable array = [ + 'Basic' + 'InstanceAndAppAdvanced' + 'WorkloadManagement' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@description('Optional. The storage account type to be used to store backups for this database.') +@allowed([ + 'Geo' + 'Local' + 'Zone' + '' +]) +param requestedBackupStorageRedundancy string = '' + +@description('Optional. Whether or not this database is a ledger database, which means all tables in the database are ledger tables. Note: the value of this property cannot be changed after the database has been created.') +param isLedgerOn bool = false + +@description('Optional. Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur.') +param maintenanceConfigurationId string = '' + +// The SKU object must be built in a variable +// The alternative, 'null' as default values, leads to non-terminating deployments +var skuVar = union({ + name: skuName + tier: skuTier +}, (skuCapacity != -1) ? { + capacity: skuCapacity +} : !empty(skuFamily) ? { + family: skuFamily +} : !empty(skuSize) ? { + size: skuSize +} : {}) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource server 'Microsoft.Sql/servers@2021-05-01-preview' existing = { + name: serverName +} + +resource database 'Microsoft.Sql/servers/databases@2021-02-01-preview' = { + name: name + parent: server + location: location + tags: tags + properties: { + collation: collation + maxSizeBytes: maxSizeBytes + sampleName: sampleName + zoneRedundant: zoneRedundant + licenseType: licenseType + readScale: readScale + minCapacity: !empty(minCapacity) ? json(minCapacity) : 0 + autoPauseDelay: !empty(autoPauseDelay) ? json(autoPauseDelay) : 0 + highAvailabilityReplicaCount: highAvailabilityReplicaCount + requestedBackupStorageRedundancy: any(requestedBackupStorageRedundancy) + isLedgerOn: isLedgerOn + maintenanceConfigurationId: !empty(maintenanceConfigurationId) ? maintenanceConfigurationId : null + } + sku: skuVar +} + +resource database_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: database +} + +@description('The name of the deployed database') +output name string = database.name + +@description('The resource ID of the deployed database') +output resourceId string = database.id + +@description('The resourceGroup of the deployed database') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/servers/databases/readme.md b/carml/1.0.1/Microsoft.Sql/servers/databases/readme.md new file mode 100644 index 000000000..cbd82e948 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/databases/readme.md @@ -0,0 +1,88 @@ +# SQL Server Database `[Microsoft.Sql/servers/databases]` + +This module deploys an Azure SQL Server. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/servers/databases` | 2021-02-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the database. | +| `serverName` | string | The Name of SQL Server | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `autoPauseDelay` | string | `''` | | Time in minutes after which database is automatically paused. | +| `collation` | string | `'SQL_Latin1_General_CP1_CI_AS'` | | The collation of the database. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[SQLInsights, AutomaticTuning, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors, DatabaseWaitStatistics, Timeouts, Blocks, Deadlocks, DevOpsOperationsAudit, SQLSecurityAuditEvents]` | `[SQLInsights, AutomaticTuning, QueryStoreRuntimeStatistics, QueryStoreWaitStatistics, Errors, DatabaseWaitStatistics, Timeouts, Blocks, Deadlocks, DevOpsOperationsAudit, SQLSecurityAuditEvents]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Basic, InstanceAndAppAdvanced, WorkloadManagement]` | `[Basic, InstanceAndAppAdvanced, WorkloadManagement]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `highAvailabilityReplicaCount` | int | `0` | | The number of readonly secondary replicas associated with the database. | +| `isLedgerOn` | bool | `False` | | Whether or not this database is a ledger database, which means all tables in the database are ledger tables. Note: the value of this property cannot be changed after the database has been created. | +| `licenseType` | string | `''` | | The license type to apply for this database. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `maintenanceConfigurationId` | string | `''` | | Maintenance configuration ID assigned to the database. This configuration defines the period when the maintenance updates will occur. | +| `maxSizeBytes` | int | `34359738368` | | The max size of the database expressed in bytes. | +| `minCapacity` | string | `''` | | Minimal capacity that database will always have allocated. | +| `readScale` | string | `'Disabled'` | `[Enabled, Disabled]` | The state of read-only routing. | +| `requestedBackupStorageRedundancy` | string | `''` | `[Geo, Local, Zone, ]` | The storage account type to be used to store backups for this database. | +| `sampleName` | string | `''` | | The name of the sample schema to apply when creating this database. | +| `skuCapacity` | int | `-1` | | Capacity of the particular SKU. | +| `skuFamily` | string | `''` | | If the service has different generations of hardware, for the same SKU, then that can be captured here. | +| `skuName` | string | `'GP_Gen5_2'` | | The name of the SKU. | +| `skuSize` | string | `''` | | Size of the particular SKU. | +| `skuTier` | string | `'GeneralPurpose'` | | The skuTier or edition of the particular SKU. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `zoneRedundant` | bool | `False` | | Whether or not this database is zone redundant. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database | +| `resourceGroupName` | string | The resourceGroup of the deployed database | +| `resourceId` | string | The resource ID of the deployed database | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Servers/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/servers/databases) diff --git a/carml/1.0.1/Microsoft.Sql/servers/databases/version.json b/carml/1.0.1/Microsoft.Sql/servers/databases/version.json new file mode 100644 index 000000000..a086a1818 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/databases/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "1.0" +} diff --git a/carml/1.0.1/Microsoft.Sql/servers/deploy.bicep b/carml/1.0.1/Microsoft.Sql/servers/deploy.bicep new file mode 100644 index 000000000..a01ca77e9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/deploy.bicep @@ -0,0 +1,177 @@ +@description('Optional. Administrator username for the server. Required if no `administrators` object for AAD authentication is provided.') +param administratorLogin string = '' + +@description('Optional. The administrator login password. Required if no `administrators` object for AAD authentication is provided.') +@secure() +param administratorLoginPassword string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The name of the server.') +param name string + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The databases to create in the server') +param databases array = [] + +@description('Optional. The firewall rules to create in the server') +param firewallRules array = [] + +@description('Optional. The security alert policies to create in the server') +param securityAlertPolicies array = [] + +@description('Optional. The Azure Active Directory (AAD) administrator authentication. Required if no `administratorLogin` & `administratorLoginPassword` is provided.') +param administrators object = {} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource server 'Microsoft.Sql/servers@2021-05-01-preview' = { + location: location + name: name + tags: tags + identity: identity + properties: { + administratorLogin: !empty(administratorLogin) ? administratorLogin : null + administratorLoginPassword: !empty(administratorLoginPassword) ? administratorLoginPassword : null + administrators: !empty(administrators) ? { + administratorType: 'ActiveDirectory' + azureADOnlyAuthentication: administrators.azureADOnlyAuthentication + login: administrators.login + principalType: administrators.principalType + sid: administrators.sid + tenantId: administrators.tenantId + } : null + version: '12.0' + } +} + +resource server_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${server.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: server +} + +module server_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Sql-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: server.id + } +}] + +module server_databases 'databases/deploy.bicep' = [for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-Sql-DB-${index}' + params: { + name: database.name + serverName: server.name + skuTier: contains(database, 'skuTier') ? database.skuTier : 'GeneralPurpose' + skuName: contains(database, 'skuName') ? database.skuName : 'GP_Gen5_2' + skuCapacity: contains(database, 'skuCapacity') ? database.skuCapacity : -1 + skuFamily: contains(database, 'skuFamily') ? database.skuFamily : '' + skuSize: contains(database, 'skuSize') ? database.skuSize : '' + collation: contains(database, 'collation') ? database.collation : 'SQL_Latin1_General_CP1_CI_AS' + maxSizeBytes: contains(database, 'maxSizeBytes') ? database.maxSizeBytes : 34359738368 + autoPauseDelay: contains(database, 'autoPauseDelay') ? database.autoPauseDelay : '' + diagnosticLogsRetentionInDays: contains(database, 'diagnosticLogsRetentionInDays') ? database.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(database, 'diagnosticStorageAccountId') ? database.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(database, 'diagnosticEventHubAuthorizationRuleId') ? database.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(database, 'diagnosticEventHubName') ? database.diagnosticEventHubName : '' + isLedgerOn: contains(database, 'isLedgerOn') ? database.isLedgerOn : false + location: contains(database, 'location') ? database.location : server.location + diagnosticLogCategoriesToEnable: contains(database, 'diagnosticLogCategoriesToEnable') ? database.diagnosticLogCategoriesToEnable : [] + licenseType: contains(database, 'licenseType') ? database.licenseType : '' + maintenanceConfigurationId: contains(database, 'maintenanceConfigurationId') ? database.maintenanceConfigurationId : '' + minCapacity: contains(database, 'minCapacity') ? database.minCapacity : '' + diagnosticMetricsToEnable: contains(database, 'diagnosticMetricsToEnable') ? database.diagnosticMetricsToEnable : [] + highAvailabilityReplicaCount: contains(database, 'highAvailabilityReplicaCount') ? database.highAvailabilityReplicaCount : 0 + readScale: contains(database, 'readScale') ? database.readScale : 'Disabled' + requestedBackupStorageRedundancy: contains(database, 'requestedBackupStorageRedundancy') ? database.requestedBackupStorageRedundancy : '' + sampleName: contains(database, 'sampleName') ? database.sampleName : '' + tags: contains(database, 'tags') ? database.tags : {} + diagnosticWorkspaceId: contains(database, 'diagnosticWorkspaceId') ? database.diagnosticWorkspaceId : '' + zoneRedundant: contains(database, 'zoneRedundant') ? database.zoneRedundant : false + } +}] + +module server_firewallRules 'firewallRules/deploy.bicep' = [for (firewallRule, index) in firewallRules: { + name: '${uniqueString(deployment().name, location)}-Sql-FirewallRules-${index}' + params: { + name: firewallRule.name + serverName: server.name + endIpAddress: contains(firewallRule, 'endIpAddress') ? firewallRule.endIpAddress : '0.0.0.0' + startIpAddress: contains(firewallRule, 'startIpAddress') ? firewallRule.startIpAddress : '0.0.0.0' + } +}] + +module server_securityAlertPolicies 'securityAlertPolicies/deploy.bicep' = [for (securityAlertPolicy, index) in securityAlertPolicies: { + name: '${uniqueString(deployment().name, location)}-Sql-SecAlertPolicy-${index}' + params: { + name: securityAlertPolicy.name + serverName: server.name + disabledAlerts: contains(securityAlertPolicy, 'disabledAlerts') ? securityAlertPolicy.disabledAlerts : [] + emailAccountAdmins: contains(securityAlertPolicy, 'emailAccountAdmins') ? securityAlertPolicy.emailAccountAdmins : false + emailAddresses: contains(securityAlertPolicy, 'emailAddresses') ? securityAlertPolicy.emailAddresses : [] + retentionDays: contains(securityAlertPolicy, 'retentionDays') ? securityAlertPolicy.retentionDays : 0 + state: contains(securityAlertPolicy, 'state') ? securityAlertPolicy.state : 'Disabled' + storageAccountAccessKey: contains(securityAlertPolicy, 'storageAccountAccessKey') ? securityAlertPolicy.storageAccountAccessKey : '' + storageEndpoint: contains(securityAlertPolicy, 'storageEndpoint') ? securityAlertPolicy.storageEndpoint : '' + } +}] + +@description('The name of the deployed SQL server') +output name string = server.name + +@description('The resource ID of the deployed SQL server') +output resourceId string = server.id + +@description('The resourceGroup of the deployed SQL server') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(server.identity, 'principalId') ? server.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Sql/servers/firewallRules/deploy.bicep b/carml/1.0.1/Microsoft.Sql/servers/firewallRules/deploy.bicep new file mode 100644 index 000000000..6702cb522 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/firewallRules/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. The name of the Server Firewall Rule.') +param name string + +@description('Optional. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') +param endIpAddress string = '0.0.0.0' + +@description('Optional. The start IP address of the firewall rule. Must be IPv4 format. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') +param startIpAddress string = '0.0.0.0' + +@description('Required. The Name of SQL Server') +param serverName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource server 'Microsoft.Sql/servers@2021-05-01-preview' existing = { + name: serverName +} + +resource firewallRule 'Microsoft.Sql/servers/firewallRules@2021-05-01-preview' = { + name: name + parent: server + properties: { + endIpAddress: endIpAddress + startIpAddress: startIpAddress + } +} + +@description('The name of the deployed firewall rule') +output name string = firewallRule.name + +@description('The resource ID of the deployed firewall rule') +output resourceId string = firewallRule.id + +@description('The resourceGroup of the deployed firewall rule') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/servers/firewallRules/readme.md b/carml/1.0.1/Microsoft.Sql/servers/firewallRules/readme.md new file mode 100644 index 000000000..6c07fc339 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/firewallRules/readme.md @@ -0,0 +1,44 @@ +# SQL Server Firewall rule `[Microsoft.Sql/servers/firewallrules]` + +This module deploys an SQL Server Firewall rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/servers/firewallRules` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Server Firewall Rule. | +| `serverName` | string | The Name of SQL Server | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endIpAddress` | string | `'0.0.0.0'` | The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. | +| `startIpAddress` | string | `'0.0.0.0'` | The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed firewall rule | +| `resourceGroupName` | string | The resourceGroup of the deployed firewall rule | +| `resourceId` | string | The resource ID of the deployed firewall rule | + +## Template references + +- [Servers/Firewallrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/firewallRules) diff --git a/carml/1.0.1/Microsoft.Sql/servers/firewallRules/version.json b/carml/1.0.1/Microsoft.Sql/servers/firewallRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/firewallRules/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/carml/1.0.1/Microsoft.Sql/servers/readme.md b/carml/1.0.1/Microsoft.Sql/servers/readme.md new file mode 100644 index 000000000..86ed5927d --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/readme.md @@ -0,0 +1,139 @@ +# SQL Servers `[Microsoft.Sql/servers]` + +This module deploys a SQL server. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Sql/servers` | 2021-05-01-preview | +| `Microsoft.Sql/servers/databases` | 2021-02-01-preview | +| `Microsoft.Sql/servers/firewallRules` | 2021-05-01-preview | +| `Microsoft.Sql/servers/securityAlertPolicies` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the server. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `administratorLogin` | string | `''` | | Administrator username for the server. Required if no `administrators` object for AAD authentication is provided. | +| `administratorLoginPassword` | secureString | `''` | | The administrator login password. Required if no `administrators` object for AAD authentication is provided. | +| `administrators` | object | `{object}` | | The Azure Active Directory (AAD) administrator authentication. Required if no `administratorLogin` & `administratorLoginPassword` is provided. | +| `databases` | _[databases](databases/readme.md)_ array | `[]` | | The databases to create in the server | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `firewallRules` | _[firewallRules](firewallRules/readme.md)_ array | `[]` | | The firewall rules to create in the server | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityAlertPolicies` | _[securityAlertPolicies](securityAlertPolicies/readme.md)_ array | `[]` | | The security alert policies to create in the server | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +### Parameter Usage: `administrators` + +Configure Azure Active Directory Authentication method for server administrator. +https://docs.microsoft.com/en-us/azure/templates/microsoft.sql/servers/administrators?tabs=bicep + +```json +"administrators": { + "value": { + "azureADOnlyAuthentication": true + "login": "John Doe" // if application can be anything + "sid": "<>" // if application, the object ID + "principalType" : "User" // options: "User", "Group", "Application" + "tenantId": "<>" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed SQL server | +| `resourceGroupName` | string | The resourceGroup of the deployed SQL server | +| `resourceId` | string | The resource ID of the deployed SQL server | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Servers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers) +- [Servers/Databases](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-02-01-preview/servers/databases) +- [Servers/Firewallrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/firewallRules) +- [Servers/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/securityAlertPolicies) diff --git a/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/deploy.bicep new file mode 100644 index 000000000..f126189eb --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/deploy.bicep @@ -0,0 +1,73 @@ +@description('Required. The name of the Security Alert Policy.') +param name string + +@description('Optional. Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force.') +param disabledAlerts array = [] + +@description('Optional. Specifies that the alert is sent to the account administrators.') +param emailAccountAdmins bool = false + +@description('Optional. Specifies an array of email addresses to which the alert is sent.') +param emailAddresses array = [] + +@description('Optional. Specifies the number of days to keep in the Threat Detection audit logs.') +param retentionDays int = 0 + +@description('Optional. Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param state string = 'Disabled' + +@description('Optional. Specifies the identifier key of the Threat Detection audit storage account..') +@secure() +param storageAccountAccessKey string = '' + +@description('Optional. Specifies the blob storage endpoint (e.g. https://mystorageaccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs.') +param storageEndpoint string = '' + +@description('Required. The Name of SQL Server') +param serverName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource server 'Microsoft.Sql/servers@2021-05-01-preview' existing = { + name: serverName +} + +resource securityAlertPolicy 'Microsoft.Sql/servers/securityAlertPolicies@2021-05-01-preview' = { + name: name + parent: server + properties: { + disabledAlerts: disabledAlerts + emailAccountAdmins: emailAccountAdmins + emailAddresses: emailAddresses + retentionDays: retentionDays + state: state + storageAccountAccessKey: empty(storageAccountAccessKey) ? null : storageAccountAccessKey + storageEndpoint: empty(storageEndpoint) ? null : storageEndpoint + } +} + +@description('The name of the deployed security alert policy') +output name string = securityAlertPolicy.name + +@description('The resource ID of the deployed security alert policy') +output resourceId string = securityAlertPolicy.id + +@description('The resourceGroup of the deployed security alert policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/readme.md b/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/readme.md new file mode 100644 index 000000000..774e7bc2d --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/readme.md @@ -0,0 +1,49 @@ +# SQL Server Security Alert Policy `[Microsoft.Sql/servers/securityAlertPolicies]` + +This module deploys an SQL Server Security Alert Policy. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Sql/servers/securityAlertPolicies` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Security Alert Policy. | +| `serverName` | string | The Name of SQL Server | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `disabledAlerts` | array | `[]` | | Specifies an array of alerts that are disabled. Allowed values are: Sql_Injection, Sql_Injection_Vulnerability, Access_Anomaly, Data_Exfiltration, Unsafe_Action, Brute_Force. | +| `emailAccountAdmins` | bool | `False` | | Specifies that the alert is sent to the account administrators. | +| `emailAddresses` | array | `[]` | | Specifies an array of email addresses to which the alert is sent. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `retentionDays` | int | `0` | | Specifies the number of days to keep in the Threat Detection audit logs. | +| `state` | string | `'Disabled'` | `[Disabled, Enabled]` | Specifies the state of the policy, whether it is enabled or disabled or a policy has not been applied yet on the specific database. | +| `storageAccountAccessKey` | secureString | `''` | | Specifies the identifier key of the Threat Detection audit storage account.. | +| `storageEndpoint` | string | `''` | | Specifies the blob storage endpoint (e.g. https://mystorageaccount.blob.core.windows.net). This blob storage will hold all Threat Detection audit logs. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed security alert policy | +| `resourceGroupName` | string | The resourceGroup of the deployed security alert policy | +| `resourceId` | string | The resource ID of the deployed security alert policy | + +## Template references + +- [Servers/Securityalertpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Sql/2021-05-01-preview/servers/securityAlertPolicies) diff --git a/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/version.json b/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/securityAlertPolicies/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/carml/1.0.1/Microsoft.Sql/servers/version.json b/carml/1.0.1/Microsoft.Sql/servers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Sql/servers/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/carml/1.0.1/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..75fa03bcd --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateDnsZoneGroups 'privateDnsZoneGroups@2021-02-01' = { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + } +} diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c1fb27d3a --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,80 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(storageAccount.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: storageAccount +}] diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..30ac50db6 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "allowBlobPublicAccess": { + "value": false + } + } +} diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/nfs.parameters.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/nfs.parameters.json new file mode 100644 index 000000000..7ae90dbda --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/nfs.parameters.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsax002" + }, + "storageAccountSku": { + "value": "Premium_LRS" + }, + "storageAccountKind": { + "value": "FileStorage" + }, + "allowBlobPublicAccess": { + "value": false + }, + "supportsHttpsTrafficOnly": { + "value": false + }, + "fileServices": { + "value": { + "shares": [ + { + "name": "nfsfileshare", + "enabledProtocols": "NFS" + } + ] + } + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/parameters.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/parameters.json new file mode 100644 index 000000000..2b0420451 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/parameters.json @@ -0,0 +1,179 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsax001" + }, + "storageAccountSku": { + "value": "Standard_LRS" + }, + "allowBlobPublicAccess": { + "value": false + }, + "publicNetworkAccess": { + "value": "Disabled" + }, + "requireInfrastructureEncryption": { + "value": true + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "blob" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "table" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "queue" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "file" + } + ] + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "blobServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "containers": [ + { + "name": "avdscripts", + "publicAccess": "None", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "archivecontainer", + "publicAccess": "None", + "enableWORM": true, + "WORMRetention": 666, + "allowProtectedAppendWrites": false + } + ] + } + }, + "fileServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "shares": [ + { + "name": "avdprofiles", + "shareQuota": "5120", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "avdprofiles2", + "shareQuota": "5120" + } + ] + } + }, + "tableServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "tables": [ + "table1", + "table2" + ] + } + }, + "queueServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "queues": [ + { + "name": "queue1", + "metadata": {}, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "queue2", + "metadata": {} + } + ] + } + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json new file mode 100644 index 000000000..c411287f9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "storageAccountKind": { + "value": "Storage" + }, + "allowBlobPublicAccess": { + "value": false + } + } +} diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ffd787fab --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep @@ -0,0 +1,71 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(container.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: container +}] diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep new file mode 100644 index 000000000..c3c07bc15 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep @@ -0,0 +1,88 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. The name of the storage container to deploy') +param name string + +@description('Optional. Name of the immutable policy.') +param immutabilityPolicyName string = 'default' + +@allowed([ + 'Container' + 'Blob' + 'None' +]) +@description('Optional. Specifies whether data in the container may be accessed publicly and the level of access.') +param publicAccess string = 'None' + +@description('Optional. Configure immutability policy.') +param immutabilityPolicyProperties object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + } +} + +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' = { + name: name + parent: storageAccount::blobServices + properties: { + publicAccess: publicAccess + } +} + +module immutabilityPolicy 'immutabilityPolicies/deploy.bicep' = if (!empty(immutabilityPolicyProperties)) { + name: immutabilityPolicyName + params: { + storageAccountName: storageAccount.name + blobServicesName: storageAccount::blobServices.name + containerName: container.name + immutabilityPeriodSinceCreationInDays: contains(immutabilityPolicyProperties, 'immutabilityPeriodSinceCreationInDays') ? immutabilityPolicyProperties.immutabilityPeriodSinceCreationInDays : 365 + allowProtectedAppendWrites: contains(immutabilityPolicyProperties, 'allowProtectedAppendWrites') ? immutabilityPolicyProperties.allowProtectedAppendWrites : true + } +} + +module container_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: container.id + } +}] + +@description('The name of the deployed container') +output name string = container.name + +@description('The resource ID of the deployed container') +output resourceId string = container.id + +@description('The resource group of the deployed container') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep new file mode 100644 index 000000000..a7c87d255 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep @@ -0,0 +1,63 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. Name of the container to apply the policy to') +param containerName string + +@description('Optional. Name of the immutable policy.') +param name string = 'default' + +@description('Optional. The immutability period for the blobs in the container since the policy creation, in days.') +param immutabilityPeriodSinceCreationInDays int = 365 + +@description('Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API') +param allowProtectedAppendWrites bool = true + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + + resource container 'containers@2019-06-01' existing = { + name: containerName + } + } +} + +resource immutabilityPolicy 'Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2019-06-01' = { + name: name + parent: storageAccount::blobServices::container + properties: { + immutabilityPeriodSinceCreationInDays: immutabilityPeriodSinceCreationInDays + allowProtectedAppendWrites: allowProtectedAppendWrites + } +} + +@description('The name of the deployed immutability policy.') +output name string = immutabilityPolicy.name + +@description('The resource ID of the deployed immutability policy.') +output resourceId string = immutabilityPolicy.id + +@description('The resource group of the deployed immutability policy.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md new file mode 100644 index 000000000..62d201778 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md @@ -0,0 +1,46 @@ +# Blob Container Immutability Policy `[Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies]` + +This module deploys an Immutability Policy for a blob container + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `containerName` | string | Name of the container to apply the policy to | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `allowProtectedAppendWrites` | bool | `True` | This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API | +| `blobServicesName` | string | `'default'` | Name of the blob service. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `immutabilityPeriodSinceCreationInDays` | int | `365` | The immutability period for the blobs in the container since the policy creation, in days. | +| `name` | string | `'default'` | Name of the immutable policy. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed immutability policy. | +| `resourceGroupName` | string | The resource group of the deployed immutability policy. | +| `resourceId` | string | The resource ID of the deployed immutability policy. | + +## Template references + +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/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/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md new file mode 100644 index 000000000..93371cb97 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md @@ -0,0 +1,77 @@ +# Storage Account Container `[Microsoft.Storage/storageAccounts/blobServices/containers]` + +This module deploys a blob container + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the storage container to deploy | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `blobServicesName` | string | `'default'` | | Name of the blob service. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `immutabilityPolicyName` | string | `'default'` | | Name of the immutable policy. | +| `immutabilityPolicyProperties` | object | `{object}` | | Configure immutability policy. | +| `publicAccess` | string | `'None'` | `[Container, Blob, None]` | Specifies whether data in the container may be accessed publicly and the level of access. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed container | +| `resourceGroupName` | string | The resource group of the deployed container | +| `resourceId` | string | The resource ID of the deployed container | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/containers/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/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep new file mode 100644 index 000000000..fd7e4a992 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep @@ -0,0 +1,142 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the blob service') +param name string = 'default' + +@description('Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service.') +param deleteRetentionPolicy bool = true + +@description('Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365.') +param deleteRetentionPolicyDays int = 7 + +@description('Optional. Automatic Snapshot is enabled if set to true.') +param automaticSnapshotPolicyEnabled bool = false + +@description('Optional. Blob containers to create.') +param containers array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource blobServices 'Microsoft.Storage/storageAccounts/blobServices@2021-06-01' = { + name: name + parent: storageAccount + properties: { + deleteRetentionPolicy: { + enabled: deleteRetentionPolicy + days: deleteRetentionPolicyDays + } + automaticSnapshotPolicyEnabled: automaticSnapshotPolicyEnabled + } +} + +resource blobServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: blobServices +} + +module blobServices_container 'containers/deploy.bicep' = [for (container, index) in containers: { + name: '${deployment().name}-Container-${index}' + params: { + storageAccountName: storageAccount.name + blobServicesName: blobServices.name + name: container.name + publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None' + roleAssignments: contains(container, 'roleAssignments') ? container.roleAssignments : [] + immutabilityPolicyProperties: contains(container, 'immutabilityPolicyProperties') ? container.immutabilityPolicyProperties : {} + } +}] + +@description('The name of the deployed blob service') +output name string = blobServices.name + +@description('The resource ID of the deployed blob service') +output resourceId string = blobServices.id + +@description('The name of the deployed blob service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/readme.md new file mode 100644 index 000000000..202404d37 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/readme.md @@ -0,0 +1,62 @@ +# Storage Account blob services `[Microsoft.Storage/storageAccounts/blobServices]` + +This module can be used to deploy a blob service into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/blobServices` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automaticSnapshotPolicyEnabled` | bool | `False` | | Automatic Snapshot is enabled if set to true. | +| `containers` | _[containers](containers/readme.md)_ array | `[]` | | Blob containers to create. | +| `deleteRetentionPolicy` | bool | `True` | | Indicates whether DeleteRetentionPolicy is enabled for the Blob service. | +| `deleteRetentionPolicyDays` | int | `7` | | Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the blob service | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed blob service | +| `resourceGroupName` | string | The name of the deployed blob service | +| `resourceId` | string | The resource ID of the deployed blob service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Blobservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/blobServices) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/blobServices/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/carml/1.0.1/Microsoft.Storage/storageAccounts/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/deploy.bicep new file mode 100644 index 000000000..733979893 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/deploy.bicep @@ -0,0 +1,360 @@ +@maxLength(24) +@description('Optional. Name of the Storage Account. Autogenerated with a unique string if not provided.') +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'Storage' + 'StorageV2' + 'BlobStorage' + 'FileStorage' + 'BlockBlobStorage' +]) +@description('Optional. Type of Storage Account to create.') +param storageAccountKind string = 'StorageV2' + +@allowed([ + 'Standard_LRS' + 'Standard_GRS' + 'Standard_RAGRS' + 'Standard_ZRS' + 'Premium_LRS' + 'Premium_ZRS' + 'Standard_GZRS' + 'Standard_RAGZRS' +]) +@description('Optional. Storage Account Sku Name.') +param storageAccountSku string = 'Standard_GRS' + +@allowed([ + 'Hot' + 'Cool' +]) +@description('Optional. Storage Account Access Tier.') +param storageAccountAccessTier string = 'Hot' + +@description('Optional. Provides the identity based authentication settings for Azure Files.') +param azureFilesIdentityBasedAuthentication object = {} + +@description('Optional. Virtual Network Identifier used to create a service endpoint.') +param vNetId string = '' + +@description('Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible') +param privateEndpoints array = [] + +@description('Optional. The Storage Account ManagementPolicies Rules.') +param managementPolicyRules array = [] + +@description('Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny') +param networkAcls object = {} + +@description('Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true.') +param requireInfrastructureEncryption bool = true + +@description('Optional. Blob service and containers to deploy') +param blobServices object = {} + +@description('Optional. File service and shares to deploy') +param fileServices object = {} + +@description('Optional. Queue service and queues to create.') +param queueServices object = {} + +@description('Optional. Table service and tables to create.') +param tableServices object = {} + +@description('Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false.') +param allowBlobPublicAccess bool = false + +@allowed([ + 'TLS1_0' + 'TLS1_1' + 'TLS1_2' +]) +@description('Optional. Set the minimum TLS version on request to storage.') +param minimumTlsVersion string = 'TLS1_2' + +@description('Optional. If true, enables Hierarchical Namespace for the storage account') +param enableHierarchicalNamespace bool = false + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param basetime string = utcNow('u') + +@allowed([ + 'Enabled' + 'Disabled' +]) + +@description('Optional. Enable or disallow public network access to Storage Account..') +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Allows HTTPS traffic only to storage service if sets to true.') +param supportsHttpsTrafficOnly bool = true + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var virtualNetworkRules = [for index in range(0, (empty(networkAcls) ? 0 : length(networkAcls.virtualNetworkRules))): { + id: '${vNetId}/subnets/${networkAcls.virtualNetworkRules[index].subnet}' +}] + +var maxNameLength = 24 +var uniqueStorageNameUntrim = '${uniqueString('Storage Account${basetime}')}' +var uniqueStorageName = length(uniqueStorageNameUntrim) > maxNameLength ? substring(uniqueStorageNameUntrim, 0, maxNameLength) : uniqueStorageNameUntrim + +var supportsBlobService = storageAccountKind == 'BlockBlobStorage' || storageAccountKind == 'BlobStorage' || storageAccountKind == 'StorageV2' || storageAccountKind == 'Storage' +var supportsFileService = storageAccountKind == 'FileStorage' || storageAccountKind == 'StorageV2' || storageAccountKind == 'Storage' + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = { + name: !empty(name) ? name : uniqueStorageName + location: location + kind: storageAccountKind + sku: { + name: storageAccountSku + } + identity: identity + tags: tags + properties: { + encryption: { + keySource: 'Microsoft.Storage' + services: { + blob: supportsBlobService ? { + enabled: true + } : null + file: supportsFileService ? { + enabled: true + } : null + } + requireInfrastructureEncryption: storageAccountKind != 'Storage' ? requireInfrastructureEncryption : null + } + accessTier: storageAccountKind != 'Storage' ? storageAccountAccessTier : null + supportsHttpsTrafficOnly: supportsHttpsTrafficOnly + isHnsEnabled: enableHierarchicalNamespace ? enableHierarchicalNamespace : null + minimumTlsVersion: minimumTlsVersion + networkAcls: !empty(networkAcls) ? { + bypass: !empty(networkAcls) ? networkAcls.bypass : null + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: !empty(networkAcls) ? virtualNetworkRules : null + ipRules: !empty(networkAcls) ? (length(networkAcls.ipRules) != 0 ? networkAcls.ipRules : null) : null + } : null + allowBlobPublicAccess: allowBlobPublicAccess + publicNetworkAccess: publicNetworkAccess + azureFilesIdentityBasedAuthentication: !empty(azureFilesIdentityBasedAuthentication) ? azureFilesIdentityBasedAuthentication : null + } +} + +resource storageAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: storageAccount +} + +resource storageAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${storageAccount.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: storageAccount +} + +module storageAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Storage-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: storageAccount.id + } +}] + +module storageAccount_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-Storage-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: storageAccount.id + privateEndpointVnetLocation: !empty(privateEndpoints) ? reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location : 'dummy' + privateEndpointObj: endpoint + tags: tags + } +}] + +// Lifecycle Policy +module storageAccount_managementPolicies 'managementPolicies/deploy.bicep' = if (!empty(managementPolicyRules)) { + name: '${uniqueString(deployment().name, location)}-Storage-ManagementPolicies' + params: { + storageAccountName: storageAccount.name + rules: managementPolicyRules + } +} + +// Containers +module storageAccount_blobServices 'blobServices/deploy.bicep' = if (!empty(blobServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-BlobServices' + params: { + storageAccountName: storageAccount.name + containers: contains(blobServices, 'containers') ? blobServices.containers : [] + automaticSnapshotPolicyEnabled: contains(blobServices, 'automaticSnapshotPolicyEnabled') ? blobServices.automaticSnapshotPolicyEnabled : false + deleteRetentionPolicy: contains(blobServices, 'deleteRetentionPolicy') ? blobServices.deleteRetentionPolicy : true + deleteRetentionPolicyDays: contains(blobServices, 'deleteRetentionPolicyDays') ? blobServices.deleteRetentionPolicyDays : 7 + diagnosticLogsRetentionInDays: contains(blobServices, 'diagnosticLogsRetentionInDays') ? blobServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(blobServices, 'diagnosticStorageAccountId') ? blobServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(blobServices, 'diagnosticEventHubAuthorizationRuleId') ? blobServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(blobServices, 'diagnosticEventHubName') ? blobServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(blobServices, 'diagnosticLogCategoriesToEnable') ? blobServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(blobServices, 'diagnosticMetricsToEnable') ? blobServices.diagnosticMetricsToEnable : [] + diagnosticWorkspaceId: contains(blobServices, 'diagnosticWorkspaceId') ? blobServices.diagnosticWorkspaceId : '' + } +} + +// File Shares +module storageAccount_fileServices 'fileServices/deploy.bicep' = if (!empty(fileServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-FileServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(fileServices, 'diagnosticLogsRetentionInDays') ? fileServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(fileServices, 'diagnosticStorageAccountId') ? fileServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(fileServices, 'diagnosticEventHubAuthorizationRuleId') ? fileServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(fileServices, 'diagnosticEventHubName') ? fileServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(fileServices, 'diagnosticLogCategoriesToEnable') ? fileServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(fileServices, 'diagnosticMetricsToEnable') ? fileServices.diagnosticMetricsToEnable : [] + protocolSettings: contains(fileServices, 'protocolSettings') ? fileServices.protocolSettings : {} + shareDeleteRetentionPolicy: contains(fileServices, 'shareDeleteRetentionPolicy') ? fileServices.shareDeleteRetentionPolicy : { + enabled: true + days: 7 + } + shares: contains(fileServices, 'shares') ? fileServices.shares : [] + diagnosticWorkspaceId: contains(fileServices, 'diagnosticWorkspaceId') ? fileServices.diagnosticWorkspaceId : '' + } +} + +// Queue +module storageAccount_queueServices 'queueServices/deploy.bicep' = if (!empty(queueServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-QueueServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(queueServices, 'diagnosticLogsRetentionInDays') ? queueServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(queueServices, 'diagnosticStorageAccountId') ? queueServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(queueServices, 'diagnosticEventHubAuthorizationRuleId') ? queueServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(queueServices, 'diagnosticEventHubName') ? queueServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(queueServices, 'diagnosticLogCategoriesToEnable') ? queueServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(queueServices, 'diagnosticMetricsToEnable') ? queueServices.diagnosticMetricsToEnable : [] + queues: contains(queueServices, 'queues') ? queueServices.queues : [] + diagnosticWorkspaceId: contains(queueServices, 'diagnosticWorkspaceId') ? queueServices.diagnosticWorkspaceId : '' + } +} + +// Table +module storageAccount_tableServices 'tableServices/deploy.bicep' = if (!empty(tableServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-TableServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(tableServices, 'diagnosticLogsRetentionInDays') ? tableServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(tableServices, 'diagnosticStorageAccountId') ? tableServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(tableServices, 'diagnosticEventHubAuthorizationRuleId') ? tableServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(tableServices, 'diagnosticEventHubName') ? tableServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(tableServices, 'diagnosticLogCategoriesToEnable') ? tableServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(tableServices, 'diagnosticMetricsToEnable') ? tableServices.diagnosticMetricsToEnable : [] + tables: contains(tableServices, 'tables') ? tableServices.tables : [] + diagnosticWorkspaceId: contains(tableServices, 'diagnosticWorkspaceId') ? tableServices.diagnosticWorkspaceId : '' + } +} + +@description('The resource ID of the deployed storage account') +output resourceId string = storageAccount.id + +@description('The name of the deployed storage account') +output name string = storageAccount.name + +@description('The resource group of the deployed storage account') +output resourceGroupName string = resourceGroup().name + +@description('The primary blob endpoint reference if blob services are deployed.') +output primaryBlobEndpoint string = !empty(blobServices) && contains(blobServices, 'containers') ? reference('Microsoft.Storage/storageAccounts/${storageAccount.name}', '2019-04-01').primaryEndpoints.blob : '' + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(storageAccount.identity, 'principalId') ? storageAccount.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep new file mode 100644 index 000000000..1ac927665 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep @@ -0,0 +1,140 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the file service') +param name string = 'default' + +@description('Optional. Protocol settings for file service') +param protocolSettings object = {} + +@description('Optional. The service properties for soft delete.') +param shareDeleteRetentionPolicy object = { + enabled: true + days: 7 +} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. File shares to create.') +param shares array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource fileServices 'Microsoft.Storage/storageAccounts/fileServices@2021-04-01' = { + name: name + parent: storageAccount + properties: { + protocolSettings: protocolSettings + shareDeleteRetentionPolicy: shareDeleteRetentionPolicy + } +} + +resource fileServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: fileServices +} + +module fileServices_shares 'shares/deploy.bicep' = [for (share, index) in shares: { + name: '${deployment().name}-shares-${index}' + params: { + storageAccountName: storageAccount.name + fileServicesName: fileServices.name + name: share.name + enabledProtocols: contains(share, 'enabledProtocols') ? share.enabledProtocols : 'SMB' + rootSquash: contains(share, 'rootSquash') ? share.rootSquash : 'NoRootSquash' + sharedQuota: contains(share, 'sharedQuota') ? share.sharedQuota : 5120 + roleAssignments: contains(share, 'roleAssignments') ? share.roleAssignments : [] + } +}] + +@description('The name of the deployed file share service') +output name string = fileServices.name + +@description('The resource ID of the deployed file share service') +output resourceId string = fileServices.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/readme.md new file mode 100644 index 000000000..00bfe0078 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/readme.md @@ -0,0 +1,59 @@ +# Storage Account file share services `[Microsoft.Storage/storageAccounts/fileServices]` + +This module can be used to deploy a file share service into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/fileServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the file service | +| `protocolSettings` | object | `{object}` | | Protocol settings for file service | +| `shareDeleteRetentionPolicy` | object | `{object}` | | The service properties for soft delete. | +| `shares` | _[shares](shares/readme.md)_ array | `[]` | | File shares to create. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Fileservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/fileServices) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts/fileServices/shares) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..8b32d3718 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep @@ -0,0 +1,80 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(fileShare.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: fileShare +}] diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep new file mode 100644 index 000000000..7e0fe99b8 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep @@ -0,0 +1,83 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the file service') +param fileServicesName string = 'default' + +@description('Required. The name of the file share to create') +param name string + +@description('Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400.') +param sharedQuota int = 5120 + +@allowed([ + 'NFS' + 'SMB' +]) +@description('Optional. The authentication protocol that is used for the file share. Can only be specified when creating a share.') +param enabledProtocols string = 'SMB' + +@allowed([ + 'AllSquash' + 'NoRootSquash' + 'RootSquash' +]) +@description('Optional. Permissions for NFS file shares are enforced by the client OS rather than the Azure Files service. Toggling the root squash behavior reduces the rights of the root user for NFS shares.') +param rootSquash string = 'NoRootSquash' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource fileService 'fileServices@2021-04-01' existing = { + name: fileServicesName + } +} + +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2021-08-01' = { + name: name + parent: storageAccount::fileService + properties: { + shareQuota: sharedQuota + rootSquash: enabledProtocols == 'NFS' ? rootSquash : null + enabledProtocols: enabledProtocols + } +} + +module fileShare_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: fileShare.id + } +}] + +@description('The name of the deployed file share') +output name string = fileShare.name + +@description('The resource ID of the deployed file share') +output resourceId string = fileShare.id + +@description('The resource group of the deployed file share') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md new file mode 100644 index 000000000..51f132548 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md @@ -0,0 +1,75 @@ +# File Share `[Microsoft.Storage/storageAccounts/fileServices/shares]` + +This module deploys a storage account file share. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the file share to create | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enabledProtocols` | string | `'SMB'` | `[NFS, SMB]` | The authentication protocol that is used for the file share. Can only be specified when creating a share. | +| `fileServicesName` | string | `'default'` | | The name of the file service | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `rootSquash` | string | `'NoRootSquash'` | `[AllSquash, NoRootSquash, RootSquash]` | Permissions for NFS file shares are enforced by the client OS rather than the Azure Files service. Toggling the root squash behavior reduces the rights of the root user for NFS shares. | +| `sharedQuota` | int | `5120` | | The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share | +| `resourceGroupName` | string | The resource group of the deployed file share | +| `resourceId` | string | The resource ID of the deployed file share | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts/fileServices/shares) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/shares/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/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/fileServices/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/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep new file mode 100644 index 000000000..5d2c4dbe5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep @@ -0,0 +1,48 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the storage container to deploy') +param name string = 'default' + +@description('Required. The Storage Account ManagementPolicies Rules') +param rules array + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +// lifecycle policy +resource managementPolicy 'Microsoft.Storage/storageAccounts/managementPolicies@2019-06-01' = if (!empty(rules)) { + name: name + parent: storageAccount + properties: { + policy: { + rules: rules + } + } +} + +@description('The resource ID of the deployed management policy') +output resourceId string = managementPolicy.name + +@description('The name of the deployed management policy') +output name string = managementPolicy.name + +@description('The resource group of the deployed management policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/readme.md new file mode 100644 index 000000000..499a6cf4e --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/readme.md @@ -0,0 +1,77 @@ +# Storage Account Management Policies `[Microsoft.Storage/storageAccounts/managementPolicies]` + +This module can be used to deploy a management policies into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/managementPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `rules` | array | The Storage Account ManagementPolicies Rules | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the storage container to deploy | + + +### Parameter Usage: `rules` + +```json +[ + { + "enabled": true, + "name": "retention-policy", + "type": "Lifecycle", + "definition": { + "actions": { + "baseBlob": { + "tierToArchive": { + "daysAfterModificationGreaterThan": 30 + }, + "delete": { + "daysAfterModificationGreaterThan": 1096 + } + }, + "snapshot": { + "delete": { + "daysAfterCreationGreaterThan": 1096 + } + } + }, + "filters": { + "blobTypes": [ + "blockBlob" + ] + } + } + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed management policy | +| `resourceGroupName` | string | The resource group of the deployed management policy | +| `resourceId` | string | The resource ID of the deployed management policy | + +## Template references + +- [Storageaccounts/Managementpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/managementPolicies) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/managementPolicies/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/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep new file mode 100644 index 000000000..56159a70c --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep @@ -0,0 +1,126 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the queue service') +param name string = 'default' + +@description('Optional. Queues to create.') +param queues array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource queueServices 'Microsoft.Storage/storageAccounts/queueServices@2021-04-01' = { + name: name + parent: storageAccount + properties: {} +} + +resource queueServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: queueServices +} + +module queueServices_queues 'queues/deploy.bicep' = [for (queue, index) in queues: { + name: '${deployment().name}-Queue-${index}' + params: { + storageAccountName: storageAccount.name + queueServicesName: queueServices.name + name: queue.name + metadata: contains(queue, 'metadata') ? queue.metadata : {} + roleAssignments: contains(queue, 'roleAssignments') ? queue.roleAssignments : [] + } +}] + +@description('The name of the deployed file share service') +output name string = queueServices.name + +@description('The resource ID of the deployed file share service') +output resourceId string = queueServices.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c01e8ecce --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep @@ -0,0 +1,77 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Dsms Role (deprecated)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b') + 'Dsms Role (do not use)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f') + 'GenevaWarmPathResourceContributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource queue 'Microsoft.Storage/storageAccounts/queueServices/queues@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queue.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: queue +}] diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep new file mode 100644 index 000000000..f40330503 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep @@ -0,0 +1,66 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the queue service') +param queueServicesName string = 'default' + +@description('Required. The name of the storage queue to deploy') +param name string + +@description('Required. A name-value pair that represents queue metadata.') +param metadata object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource queueServices 'queueServices@2021-06-01' existing = { + name: queueServicesName + } +} + +resource queue 'Microsoft.Storage/storageAccounts/queueServices/queues@2019-06-01' = { + name: name + parent: storageAccount::queueServices + properties: { + metadata: metadata + } +} + +module queue_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: '${queue.id}' + } +}] + +@description('The name of the deployed queue') +output name string = queue.name + +@description('The resource ID of the deployed queue') +output resourceId string = queue.id + +@description('The resource group of the deployed queue') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md new file mode 100644 index 000000000..afbcaa568 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md @@ -0,0 +1,73 @@ +# Storage Account Queue `[Microsoft.Storage/storageAccounts/queueServices/queues]` + +This module deploys a storage account queue + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `metadata` | object | A name-value pair that represents queue metadata. | +| `name` | string | The name of the storage queue to deploy | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `queueServicesName` | string | `'default'` | The name of the queue service | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed queue | +| `resourceGroupName` | string | The resource group of the deployed queue | +| `resourceId` | string | The resource ID of the deployed queue | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/queues/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/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/readme.md new file mode 100644 index 000000000..45bfc3f04 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/readme.md @@ -0,0 +1,57 @@ +# Storage Account Queue Services `[Microsoft.Storage/storageAccounts/queueServices]` + +This module can be used to deploy a file share service into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/queueServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the queue service | +| `queues` | _[queues](queues/readme.md)_ array | `[]` | | Queues to create. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Queueservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/queueServices) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/queueServices/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/carml/1.0.1/Microsoft.Storage/storageAccounts/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/readme.md new file mode 100644 index 000000000..f88f0c2b0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/readme.md @@ -0,0 +1,220 @@ +# Storage Accounts `[Microsoft.Storage/storageAccounts]` + +This module is used to deploy a storage account, with the ability to deploy 1 or more blob containers, file shares, tables and queues. Optional ACLs can be configured on the storage account and optional RBAC can be assigned on the storage account and on each child resource. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | +| `Microsoft.Storage/storageAccounts` | 2021-08-01 | +| `Microsoft.Storage/storageAccounts/blobServices` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/fileServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2021-08-01 | +| `Microsoft.Storage/storageAccounts/managementPolicies` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/queueServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/tableServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBlobPublicAccess` | bool | `False` | | Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false. | +| `azureFilesIdentityBasedAuthentication` | object | `{object}` | | Provides the identity based authentication settings for Azure Files. | +| `blobServices` | _[blobServices](blobServices/readme.md)_ object | `{object}` | | Blob service and containers to deploy | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableHierarchicalNamespace` | bool | `False` | | If true, enables Hierarchical Namespace for the storage account | +| `fileServices` | _[fileServices](fileServices/readme.md)_ object | `{object}` | | File service and shares to deploy | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managementPolicyRules` | array | `[]` | | The Storage Account ManagementPolicies Rules. | +| `minimumTlsVersion` | string | `'TLS1_2'` | `[TLS1_0, TLS1_1, TLS1_2]` | Set the minimum TLS version on request to storage. | +| `name` | string | `''` | | Name of the Storage Account. Autogenerated with a unique string if not provided. | +| `networkAcls` | object | `{object}` | | Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible | +| `publicNetworkAccess` | string | `'Enabled'` | `[Enabled, Disabled]` | Enable or disallow public network access to Storage Account.. | +| `queueServices` | _[queueServices](queueServices/readme.md)_ object | `{object}` | | Queue service and queues to create. | +| `requireInfrastructureEncryption` | bool | `True` | | A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `storageAccountAccessTier` | string | `'Hot'` | `[Hot, Cool]` | Storage Account Access Tier. | +| `storageAccountKind` | string | `'StorageV2'` | `[Storage, StorageV2, BlobStorage, FileStorage, BlockBlobStorage]` | Type of Storage Account to create. | +| `storageAccountSku` | string | `'Standard_GRS'` | `[Standard_LRS, Standard_GRS, Standard_RAGRS, Standard_ZRS, Premium_LRS, Premium_ZRS, Standard_GZRS, Standard_RAGZRS]` | Storage Account Sku Name. | +| `supportsHttpsTrafficOnly` | bool | `True` | | Allows HTTPS traffic only to storage service if sets to true. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tableServices` | _[tableServices](tableServices/readme.md)_ object | `{object}` | | Table service and tables to create. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vNetId` | string | `''` | | Virtual Network Identifier used to create a service endpoint. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `basetime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a SAS token to access the modules. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "subnet": "sharedsvcs" + } + ], + "ipRules": [] + } +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed storage account | +| `primaryBlobEndpoint` | string | The primary blob endpoint reference if blob services are deployed. | +| `resourceGroupName` | string | The resource group of the deployed storage account | +| `resourceId` | string | The resource ID of the deployed storage account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +This is a generic module for deploying a Storage Account. Any customization for different storage needs (such as a diagnostic or other storage account) need to be done through the Archetype. +The hierarchical namespace of the storage account (see parameter `enableHierarchicalNamespace`), can be only set at creation time. + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts) +- [Storageaccounts/Blobservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/blobServices) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) +- [Storageaccounts/Fileservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/fileServices) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts/fileServices/shares) +- [Storageaccounts/Managementpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/managementPolicies) +- [Storageaccounts/Queueservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/queueServices) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) +- [Storageaccounts/Tableservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/tableServices) +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep new file mode 100644 index 000000000..81a2fb78f --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep @@ -0,0 +1,124 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the table service') +param name string = 'default' + +@description('Optional. tables to create.') +param tables array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource tableServices 'Microsoft.Storage/storageAccounts/tableServices@2021-04-01' = { + name: name + parent: storageAccount + properties: {} +} + +resource tableServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: tableServices +} + +module tableServices_tables 'tables/deploy.bicep' = [for (tableName, index) in tables: { + name: '${deployment().name}-Table-${index}' + params: { + storageAccountName: storageAccount.name + tableServicesName: tableServices.name + name: tableName + } +}] + +@description('The name of the deployed table service') +output name string = tableServices.name + +@description('The resource ID of the deployed table service') +output resourceId string = tableServices.id + +@description('The resource group of the deployed table service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/readme.md new file mode 100644 index 000000000..399f3561e --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/readme.md @@ -0,0 +1,55 @@ +# Storage Account Table Services `[Microsoft.Storage/storageAccounts/tableServices]` + +This module deploys a storage account table service + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/tableServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the table service | +| `tables` | _[tables](tables/readme.md)_ array | `[]` | | tables to create. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed table service | +| `resourceGroupName` | string | The resource group of the deployed table service | +| `resourceId` | string | The resource ID of the deployed table service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Storageaccounts/Tableservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/tableServices) +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep new file mode 100644 index 000000000..04a702ed5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep @@ -0,0 +1,46 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the table service') +param tableServicesName string = 'default' + +@description('Required. Name of the table.') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource tableServices 'tableServices@2021-04-01' existing = { + name: tableServicesName + } +} + +resource table 'Microsoft.Storage/storageAccounts/tableServices/tables@2021-06-01' = { + name: name + parent: storageAccount::tableServices +} + +@description('The name of the deployed file share service') +output name string = table.name + +@description('The resource ID of the deployed file share service') +output resourceId string = table.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md new file mode 100644 index 000000000..cd164e271 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md @@ -0,0 +1,43 @@ +# Storage Account Table `[Microsoft.Storage/storageAccounts/tableServices/tables]` + +This module deploys a storage account table + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the table. | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `tableServicesName` | string | `'default'` | The name of the table service | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/tables/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/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/tableServices/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/carml/1.0.1/Microsoft.Storage/storageAccounts/version.json b/carml/1.0.1/Microsoft.Storage/storageAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Storage/storageAccounts/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/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..f855b992b --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,50 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}' + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : [] + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + parent: privateEndpoint +} diff --git a/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ef867c9d0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateLinkHub 'Microsoft.Synapse/privateLinkHubs@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateLinkHub.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: privateLinkHub +}] diff --git a/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.parameters/min.parameters.json new file mode 100644 index 000000000..8b3b8868e --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "synplhmin001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.parameters/parameters.json b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.parameters/parameters.json new file mode 100644 index 000000000..e9bb15fdb --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/.parameters/parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "synplhstandard001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": ["<>"] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "principalIds": ["<>"] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/deploy.bicep b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/deploy.bicep new file mode 100644 index 000000000..8aca7e8ff --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/deploy.bicep @@ -0,0 +1,85 @@ +@description('Required. The name of the Private Link Hub.') +param name string + +@description('Optional. The geo-location where the resource lives.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateLinkHub 'Microsoft.Synapse/privateLinkHubs@2021-06-01' = { + name: name + location: location + tags: tags +} + +// Resource Lock +resource privateLinkHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateLinkHub.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateLinkHub +} + +// RBAC +module privateLinkHub_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateLinkHub.id + } +}] + +// Private Endpoints +module privateLinkHub_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: privateLinkHub.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The resource ID of the deployed Synapse Private Link Hub.') +output resourceId string = privateLinkHub.id + +@description('The name of the deployed Synapse Private Link Hub.') +output name string = privateLinkHub.name + +@description('The resource group of the deployed Synapse Private Link Hub.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/readme.md b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/readme.md new file mode 100644 index 000000000..86687b7a7 --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/readme.md @@ -0,0 +1,133 @@ +# Azure Synapse Analytics `[Microsoft.Synapse/privateLinkHubs]` + +This module deploys Azure Synapse Analytics (private link hubs). + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.Synapse/privateLinkHubs` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Private Link Hub. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | The geo-location where the resource lives. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed Synapse Private Link Hub. | +| `resourceGroupName` | string | The resource group of the deployed Synapse Private Link Hub. | +| `resourceId` | string | The resource ID of the deployed Synapse Private Link Hub. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Privatelinkhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Synapse/2021-06-01/privateLinkHubs) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/version.json b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Synapse/privateLinkHubs/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/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..f86988517 --- /dev/null +++ b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2020-02-14' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(imageTemplate.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: imageTemplate +}] diff --git a/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/.parameters/parameters.json b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/.parameters/parameters.json new file mode 100644 index 000000000..4b1b66c31 --- /dev/null +++ b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/.parameters/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": "<>-az-imgt-x-001" + }, + "userMsiName": { + "value": "adp-<>-az-msi-x-001" + }, + "userMsiResourceGroup": { + "value": "validation-rg" + }, + "buildTimeoutInMinutes": { + "value": 0 + }, + "vmSize": { + "value": "Standard_D2s_v3" + }, + "osDiskSizeGB": { + "value": 127 + }, + "subnetId": { + "value": "" + }, + "imageSource": { + "value": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-10", + "sku": "19h2-evd", + "version": "latest" + } + }, + "customizationSteps": { + "value": [ + { + "type": "WindowsRestart", + "restartTimeout": "30m" + } + ] + }, + "managedImageName": { + "value": "<>-az-mi-x-001" + }, + "unManagedImageName": { + "value": "<>-az-umi-x-001" + }, + "sigImageDefinitionId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/galleries/adp<>azsigweux001/images/adp-<>-az-imgd-x-001" + }, + "imageReplicationRegions": { + "value": [] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep new file mode 100644 index 000000000..974478571 --- /dev/null +++ b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep @@ -0,0 +1,188 @@ +@description('Required. Name of the Image Template to be built by the Azure Image Builder service.') +param name string + +@description('Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder.') +param userMsiName string + +@description('Optional. Resource group of the user assigned identity.') +param userMsiResourceGroup string = resourceGroup().name + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes') +@minValue(0) +@maxValue(960) +param buildTimeoutInMinutes int = 0 + +@description('Optional. Specifies the size for the VM.') +param vmSize string = 'Standard_D2s_v3' + +@description('Optional. Specifies the size of OS disk.') +param osDiskSizeGB int = 128 + +@description('Optional. Resource ID of an already existing subnet, e.g. \'/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/\'. If no value is provided, a new VNET will be created in the target Resource Group.') +param subnetId string = '' + +@description('Required. Image source definition in object format.') +param imageSource object + +@description('Required. Customization steps to be run when building the VM image.') +param customizationSteps array + +@description('Optional. Name of the managed image that will be created in the AIB resourcegroup.') +param managedImageName string = '' + +@description('Optional. Name of the unmanaged image that will be created in the AIB resourcegroup.') +param unManagedImageName string = '' + +@description('Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/') +param sigImageDefinitionId string = '' + +@description('Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment\'s location will be taken as a default value.') +param imageReplicationRegions array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +var managedImageName_var = '${managedImageName}-${baseTime}' +var managedImageId = '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Compute/images/${managedImageName_var}' +var imageReplicationRegions_var = empty(imageReplicationRegions) ? array(location) : imageReplicationRegions + +var managedImage = { + type: 'ManagedImage' + imageId: managedImageId + location: location + runOutputName: '${managedImageName_var}-ManagedImage' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } +} +var conditionalManagedImage = empty(managedImageName) ? [] : array(managedImage) +var sharedImage = { + type: 'SharedImage' + galleryImageId: sigImageDefinitionId + runOutputName: !empty(sigImageDefinitionId) ? '${split(sigImageDefinitionId, '/')[10]}-SharedImage' : 'SharedImage' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } + replicationRegions: imageReplicationRegions_var +} +var conditionalSharedImage = empty(sigImageDefinitionId) ? [] : array(sharedImage) +var unManagedImage = { + type: 'VHD' + runOutputName: '${unManagedImageName}-VHD' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } +} +var conditionalUnManagedImage = empty(unManagedImageName) ? [] : array(unManagedImage) +var distribute = concat(conditionalManagedImage, conditionalSharedImage, conditionalUnManagedImage) +var vnetConfig = { + subnetId: subnetId +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2020-02-14' = { + name: '${name}-${baseTime}' + location: location + tags: tags + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${az.resourceId(userMsiResourceGroup, 'Microsoft.ManagedIdentity/userAssignedIdentities', userMsiName)}': {} + } + } + properties: { + buildTimeoutInMinutes: buildTimeoutInMinutes + vmProfile: { + vmSize: vmSize + osDiskSizeGB: osDiskSizeGB + vnetConfig: !empty(subnetId) ? vnetConfig : null + } + source: imageSource + customize: customizationSteps + distribute: distribute + } +} + +resource imageTemplate_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${imageTemplate.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: imageTemplate +} + +module imageTemplate_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ImageTemplate-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: imageTemplate.id + } +}] + +@description('The resource ID of the image template') +output resourceId string = imageTemplate.id + +@description('The resource group the image template was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image template') +output name string = imageTemplate.name + +@description('The command to run in order to trigger the image build') +output runThisCommand string = 'Invoke-AzResourceAction -ResourceName ${imageTemplate.name} -ResourceGroupName ${resourceGroup().name} -ResourceType Microsoft.VirtualMachineImages/imageTemplates -Action Run -Force' diff --git a/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/readme.md b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/readme.md new file mode 100644 index 000000000..22d28c6c6 --- /dev/null +++ b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/readme.md @@ -0,0 +1,144 @@ +# Image Templates `[Microsoft.VirtualMachineImages/imageTemplates]` + +This module deploys an image template that can be consumed by the Azure Image Builder (AIB) service. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.VirtualMachineImages/imageTemplates` | 2020-02-14 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `customizationSteps` | array | Customization steps to be run when building the VM image. | +| `imageSource` | object | Image source definition in object format. | +| `name` | string | Name of the Image Template to be built by the Azure Image Builder service. | +| `userMsiName` | string | Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `buildTimeoutInMinutes` | int | `0` | | Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `imageReplicationRegions` | array | `[]` | | List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment's location will be taken as a default value. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managedImageName` | string | `''` | | Name of the managed image that will be created in the AIB resourcegroup. | +| `osDiskSizeGB` | int | `128` | | Specifies the size of OS disk. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sigImageDefinitionId` | string | `''` | | Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/ | +| `subnetId` | string | `''` | | Resource ID of an already existing subnet, e.g. '/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/'. If no value is provided, a new VNET will be created in the target Resource Group. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `unManagedImageName` | string | `''` | | Name of the unmanaged image that will be created in the AIB resourcegroup. | +| `userMsiResourceGroup` | string | `[resourceGroup().name]` | | Resource group of the user assigned identity. | +| `vmSize` | string | `'Standard_D2s_v3'` | | Specifies the size for the VM. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('yyyy-MM-dd-HH-mm-ss')]` | Do not provide a value! This date value is used to generate a unique image template name. | + + +### Parameter Usage: `imageSource` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +#### Platform Image + +```json +"source": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-10", + "sku": "19h2-evd", + "version": "latest" +} +``` + +#### Managed Image + +```json +"source": { + "type": "ManagedImage", + "imageId": "/subscriptions//resourceGroups/{destinationResourceGroupName}/providers/Microsoft.Compute/images/" +} +``` + +#### Shared Image + +```json +"source": { + "type": "SharedImageVersion", + "imageVersionID": "/subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/" +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image template | +| `resourceGroupName` | string | The resource group the image template was deployed into | +| `resourceId` | string | The resource ID of the image template | +| `runThisCommand` | string | The command to run in order to trigger the image build | + +## Template references + +- [Imagetemplates](https://docs.microsoft.com/en-us/azure/templates/Microsoft.VirtualMachineImages/2020-02-14/imageTemplates) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/version.json b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.VirtualMachineImages/imageTemplates/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/carml/1.0.1/Microsoft.Web/connections/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Web/connections/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d03c12fc4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/connections/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource connection 'Microsoft.Web/connections@2016-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(connection.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: connection +}] diff --git a/carml/1.0.1/Microsoft.Web/connections/.parameters/parameters.json b/carml/1.0.1/Microsoft.Web/connections/.parameters/parameters.json new file mode 100644 index 000000000..920f8784b --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/connections/.parameters/parameters.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "azuremonitor" + }, + "connectionKind": { + "value": "V1" + }, + "displayName": { + "value": "azuremonitorlogs" + }, + "connectionApi": { + "value": { + "id": "/subscriptions/<>/providers/Microsoft.Web/locations/westeurope/managedApis/azuremonitorlogs" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/connections/deploy.bicep b/carml/1.0.1/Microsoft.Web/connections/deploy.bicep new file mode 100644 index 000000000..879ac6560 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/connections/deploy.bicep @@ -0,0 +1,112 @@ +@description('Optional. Alternative parameter values.') +param alternativeParameterValues object = {} + +@description('Optional. Specific values for some API connections.') +param connectionApi object = {} + +@description('Required. Connection Kind. Example: \'V1\' when using blobs. It can change depending on the resource.') +param connectionKind string + +@description('Required. Connection name for connection. Example: \'azureblob\' when using blobs. It can change depending on the resource.') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Customized parameter values for specific connections.') +param customParameterValues object = {} + +@description('Required. Display name connection. Example: \'blobconnection\' when using blobs. It can change depending on the resource.') +param displayName string + +@description('Optional. Location of the deployment.') +param location string = resourceGroup().location + +@description('Optional. Dictionary of nonsecret parameter values.') +param nonSecretParameterValues object = {} + +@description('Optional. Connection strings or access keys for connection. Example: \'accountName\' and \'accessKey\' when using blobs. It can change depending on the resource.') +@secure() +param parameterValues object = {} + +@description('Optional. Value Type of parameter, in case alternativeParameterValues is used.') +param parameterValueType string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Status of the connection.') +param statuses array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Links to test the API connection.') +param testLinks array = [] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource connection 'Microsoft.Web/connections@2016-06-01' = { + name: name + location: location + kind: connectionKind + tags: tags + properties: { + displayName: displayName + customParameterValues: customParameterValues + parameterValueType: !empty(parameterValueType) ? parameterValueType : null + alternativeParameterValues: !empty(alternativeParameterValues) ? alternativeParameterValues : null + api: connectionApi + parameterValues: empty(alternativeParameterValues) ? parameterValues : null + nonSecretParameterValues: !empty(nonSecretParameterValues) ? nonSecretParameterValues : null + testLinks: !empty(testLinks) ? testLinks : null + statuses: !empty(statuses) ? statuses : null + } +} + +resource connection_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${connection.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: connection +} + +module connection_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Connection-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: connection.id + } +}] + +@description('The resource ID of the connection') +output resourceId string = connection.id + +@description('The resource group the connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the connection') +output name string = connection.name diff --git a/carml/1.0.1/Microsoft.Web/connections/readme.md b/carml/1.0.1/Microsoft.Web/connections/readme.md new file mode 100644 index 000000000..51dd83de0 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/connections/readme.md @@ -0,0 +1,153 @@ +# API Connections `[Microsoft.Web/connections]` + +This module deploys an Azure API connection. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Web/connections` | 2016-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `connectionKind` | string | Connection Kind. Example: 'V1' when using blobs. It can change depending on the resource. | +| `displayName` | string | Display name connection. Example: 'blobconnection' when using blobs. It can change depending on the resource. | +| `name` | string | Connection name for connection. Example: 'azureblob' when using blobs. It can change depending on the resource. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `alternativeParameterValues` | object | `{object}` | | Alternative parameter values. | +| `connectionApi` | object | `{object}` | | Specific values for some API connections. | +| `customParameterValues` | object | `{object}` | | Customized parameter values for specific connections. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location of the deployment. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `nonSecretParameterValues` | object | `{object}` | | Dictionary of nonsecret parameter values. | +| `parameterValues` | secureObject | `{object}` | | Connection strings or access keys for connection. Example: 'accountName' and 'accessKey' when using blobs. It can change depending on the resource. | +| `parameterValueType` | string | `''` | | Value Type of parameter, in case alternativeParameterValues is used. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `statuses` | array | `[]` | | Status of the connection. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `testLinks` | array | `[]` | | Links to test the API connection. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `connectionApi` + +```json +"connectionApi": { + "value": { + "id": "string", + "type": "string", + "swagger": {}, + "brandColor": "string", + "description": "string", + "displayName": "string", + "iconUri": "string", + "name": "string" + } +} +``` + +### Parameter Usage: `statuses` + +```json +"statuses": { + "value": [ + { + "status": "string", + "target": "string", + "error": { + "location": "string", + "tags": {}, + "properties": { + "code": "string", + "message": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `testLinks` + +```json +"testLinks": { + "value":[ + { + "requestUri": "string", + "method": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the connection | +| `resourceGroupName` | string | The resource group the connection was deployed into | +| `resourceId` | string | The resource ID of the connection | + +## Template references + +- [Connections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2016-06-01/connections) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Web/connections/version.json b/carml/1.0.1/Microsoft.Web/connections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/connections/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/carml/1.0.1/Microsoft.Web/hostingEnvironments/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Web/hostingEnvironments/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c402e2633 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/hostingEnvironments/.bicep/nested_rbac.bicep @@ -0,0 +1,54 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') +} + +resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2021-02-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appServiceEnvironment.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: appServiceEnvironment +}] diff --git a/carml/1.0.1/Microsoft.Web/hostingEnvironments/.parameters/parameters.json b/carml/1.0.1/Microsoft.Web/hostingEnvironments/.parameters/parameters.json new file mode 100644 index 000000000..cce2a3631 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/hostingEnvironments/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-appse-x-001" + }, + "subnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-006" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/hostingEnvironments/deploy.bicep b/carml/1.0.1/Microsoft.Web/hostingEnvironments/deploy.bicep new file mode 100644 index 000000000..b9f90d86b --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/hostingEnvironments/deploy.bicep @@ -0,0 +1,209 @@ +@description('Required. Name of the App Service Environment') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Kind of resource.') +param kind string = 'ASEV2' + +@description('Required. ResourceId for the sub net') +param subnetResourceId string + +@description('Optional. Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing') +@allowed([ + 'None' + 'Web' + 'Publishing' +]) +param internalLoadBalancingMode string = 'None' + +@description('Optional. Frontend VM size, e.g. Medium, Large') +@allowed([ + 'Medium' + 'Large' + 'ExtraLarge' + 'Standard_D2' + 'Standard_D3' + 'Standard_D4' + 'Standard_D1_V2' + 'Standard_D2_V2' + 'Standard_D3_V2' + 'Standard_D4_V2' +]) +param multiSize string = 'Standard_D1_V2' + +@description('Optional. Number of frontend instances.') +param multiRoleCount int = 2 + +@description('Optional. Number of IP SSL addresses reserved for the App Service Environment.') +param ipsslAddressCount int = 2 + +@description('Optional. Description of worker pools with worker size IDs, VM sizes, and number of workers in each pool..') +param workerPools array = [] + +@description('Optional. DNS suffix of the App Service Environment.') +param dnsSuffix string = '' + +@description('Optional. Access control list for controlling traffic to the App Service Environment..') +param networkAccessControlList array = [] + +@description('Optional. Scale factor for frontends.') +param frontEndScaleFactor int = 15 + +@description('Optional. API Management Account associated with the App Service Environment.') +param apiManagementAccountId string = '' + +@description('Optional. true if the App Service Environment is suspended; otherwise, false. The environment can be suspended, e.g. when the management endpoint is no longer available (most likely because NSG blocked the incoming traffic).') +param suspended bool = false + +@description('Optional. True/false indicating whether the App Service Environment is suspended. The environment can be suspended e.g. when the management endpoint is no longer available(most likely because NSG blocked the incoming traffic).') +param dynamicCacheEnabled bool = false + +@description('Optional. User added ip ranges to whitelist on ASE db - string') +param userWhitelistedIpRanges array = [] + +@description('Optional. Flag that displays whether an ASE has linux workers or not') +param hasLinuxWorkers bool = false + +@description('Optional. Custom settings for changing the behavior of the App Service Environment') +param clusterSettings array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AppServiceEnvironmentPlatformLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AppServiceEnvironmentPlatformLogs' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var vnetResourceId = split(subnetResourceId, '/') + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource appServiceEnvironment 'Microsoft.Web/hostingEnvironments@2021-02-01' = { + name: name + kind: kind + location: location + tags: tags + properties: { + name: name + location: location + virtualNetwork: { + id: subnetResourceId + subnet: last(vnetResourceId) + } + internalLoadBalancingMode: internalLoadBalancingMode + multiSize: multiSize + multiRoleCount: multiRoleCount + workerPools: workerPools + ipsslAddressCount: ipsslAddressCount + dnsSuffix: dnsSuffix + networkAccessControlList: networkAccessControlList + frontEndScaleFactor: frontEndScaleFactor + apiManagementAccountId: apiManagementAccountId + suspended: suspended + dynamicCacheEnabled: dynamicCacheEnabled + clusterSettings: clusterSettings + userWhitelistedIpRanges: userWhitelistedIpRanges + hasLinuxWorkers: hasLinuxWorkers + } +} + +resource appServiceEnvironment_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appServiceEnvironment.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appServiceEnvironment +} + +resource appServiceEnvironment_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: appServiceEnvironment +} + +module appServiceEnvironment_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppServiceEnv-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appServiceEnvironment.id + } +}] + +@description('The resource ID of the app service environment') +output resourceId string = appServiceEnvironment.id + +@description('The resource group the app service environment was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the app service environment') +output name string = appServiceEnvironment.name diff --git a/carml/1.0.1/Microsoft.Web/hostingEnvironments/readme.md b/carml/1.0.1/Microsoft.Web/hostingEnvironments/readme.md new file mode 100644 index 000000000..ae79f485d --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/hostingEnvironments/readme.md @@ -0,0 +1,165 @@ +# App Service Environments `[Microsoft.Web/hostingEnvironments]` + +This module deploys an app service environment. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Web/hostingEnvironments` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the App Service Environment | +| `subnetResourceId` | string | ResourceId for the sub net | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiManagementAccountId` | string | `''` | | API Management Account associated with the App Service Environment. | +| `clusterSettings` | array | `[]` | | Custom settings for changing the behavior of the App Service Environment | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[AppServiceEnvironmentPlatformLogs]` | `[AppServiceEnvironmentPlatformLogs]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `dnsSuffix` | string | `''` | | DNS suffix of the App Service Environment. | +| `dynamicCacheEnabled` | bool | `False` | | True/false indicating whether the App Service Environment is suspended. The environment can be suspended e.g. when the management endpoint is no longer available(most likely because NSG blocked the incoming traffic). | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `frontEndScaleFactor` | int | `15` | | Scale factor for frontends. | +| `hasLinuxWorkers` | bool | `False` | | Flag that displays whether an ASE has linux workers or not | +| `internalLoadBalancingMode` | string | `'None'` | `[None, Web, Publishing]` | Specifies which endpoints to serve internally in the Virtual Network for the App Service Environment. - None, Web, Publishing, Web,Publishing | +| `ipsslAddressCount` | int | `2` | | Number of IP SSL addresses reserved for the App Service Environment. | +| `kind` | string | `'ASEV2'` | | Kind of resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `multiRoleCount` | int | `2` | | Number of frontend instances. | +| `multiSize` | string | `'Standard_D1_V2'` | `[Medium, Large, ExtraLarge, Standard_D2, Standard_D3, Standard_D4, Standard_D1_V2, Standard_D2_V2, Standard_D3_V2, Standard_D4_V2]` | Frontend VM size, e.g. Medium, Large | +| `networkAccessControlList` | array | `[]` | | Access control list for controlling traffic to the App Service Environment.. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `suspended` | bool | `False` | | true if the App Service Environment is suspended; otherwise, false. The environment can be suspended, e.g. when the management endpoint is no longer available (most likely because NSG blocked the incoming traffic). | +| `tags` | object | `{object}` | | Resource tags. | +| `userWhitelistedIpRanges` | array | `[]` | | User added ip ranges to whitelist on ASE db - string | +| `workerPools` | array | `[]` | | Description of worker pools with worker size IDs, VM sizes, and number of workers in each pool.. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `workerPools` + +```json +"workerPools": { + "value": { + "workerPools": [ + { + "workerSizeId": 0, + "workerSize": "Small", + "workerCount": 2 + }, + { + "workerSizeId": 1, + "workerSize": "Small", + "workerCount": 2 + } + ] + } +} +``` + +workerPools can have two properties workerSize and workerCount: + +```json + "workerSize": { + "type": "string", + "allowedValues": [ + "Small", + "Medium", + "Large", + "ExtraLarge" + ], + "defaultValue": "Small", + "metadata": { + "description": "Instance size for worker pool one. Maps to P1,P2,P3,P4." + } + }, + "workerCount": { + "type": "int", + "defaultValue": 2, + "minValue": 2, + "maxValue": 100, + "metadata": { + "description": "Number of instances in worker pool one. Minimum of two." + } + } +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the app service environment | +| `resourceGroupName` | string | The resource group the app service environment was deployed into | +| `resourceId` | string | The resource ID of the app service environment | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Hostingenvironments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-02-01/hostingEnvironments) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.0.1/Microsoft.Web/hostingEnvironments/version.json b/carml/1.0.1/Microsoft.Web/hostingEnvironments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/hostingEnvironments/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/carml/1.0.1/Microsoft.Web/serverfarms/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Web/serverfarms/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..806b2b954 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/serverfarms/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') +} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appServicePlan.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: appServicePlan +}] diff --git a/carml/1.0.1/Microsoft.Web/serverfarms/.parameters/parameters.json b/carml/1.0.1/Microsoft.Web/serverfarms/.parameters/parameters.json new file mode 100644 index 000000000..2a311c3ec --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/serverfarms/.parameters/parameters.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-asp-x-001" + }, + "sku": { + "value": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": "1" + } + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/serverfarms/deploy.bicep b/carml/1.0.1/Microsoft.Web/serverfarms/deploy.bicep new file mode 100644 index 000000000..d02b14544 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/serverfarms/deploy.bicep @@ -0,0 +1,182 @@ +// ================ // +// Parameters // +// ================ // +@description('Required. The name of the app service plan to deploy.') +@minLength(1) +@maxLength(40) +param name string + +@description('Required. Defines the name, tier, size, family and capacity of the App Service Plan.') +param sku object + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Kind of server OS.') +@allowed([ + 'Windows' + 'Linux' +]) +param serverOS string = 'Windows' + +@description('Optional. The Resource ID of the App Service Environment to use for the App Service Plan.') +param appServiceEnvironmentId string = '' + +@description('Optional. Target worker tier assigned to the App Service plan.') +param workerTierName string = '' + +@description('Optional. If true, apps assigned to this App Service plan can be scaled independently. If false, apps assigned to this App Service plan will scale to all instances of the plan.') +param perSiteScaling bool = false + +@description('Optional. Maximum number of total workers allowed for this ElasticScaleEnabled App Service Plan.') +param maximumElasticWorkerCount int = 1 + +@description('Optional. Scaling worker count.') +param targetWorkerCount int = 0 + +@description('Optional. The instance size of the hosting plan (small, medium, or large).') +@allowed([ + 0 + 1 + 2 +]) +param targetWorkerSize int = 0 + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +// =========== // +// Variables // +// =========== // +var hostingEnvironmentProfile = { + id: appServiceEnvironmentId +} + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +// =========== // +// Deployments // +// =========== // +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = { + name: name + kind: serverOS == 'Windows' ? '' : 'linux' + location: location + tags: tags + sku: sku + properties: { + workerTierName: workerTierName + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? hostingEnvironmentProfile : null + perSiteScaling: perSiteScaling + maximumElasticWorkerCount: maximumElasticWorkerCount + reserved: serverOS == 'Linux' + targetWorkerCount: targetWorkerCount + targetWorkerSizeId: targetWorkerSize + } +} + +resource appServicePlan_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: [] + } + scope: appServicePlan +} + +resource appServicePlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appServicePlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appServicePlan +} + +module appServicePlan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppServicePlan-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appServicePlan.id + } +}] + +// =========== // +// Outputs // +// =========== // +@description('The resource group the app service plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the app service plan') +output name string = appServicePlan.name + +@description('The resource ID of the app service plan') +output resourceId string = appServicePlan.id diff --git a/carml/1.0.1/Microsoft.Web/serverfarms/readme.md b/carml/1.0.1/Microsoft.Web/serverfarms/readme.md new file mode 100644 index 000000000..1d07c09b9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/serverfarms/readme.md @@ -0,0 +1,123 @@ +# App Service Plans `[Microsoft.Web/serverfarms]` + +This module deploys an app service plan. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Web/serverfarms` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the app service plan to deploy. | +| `sku` | object | Defines the name, tier, size, family and capacity of the App Service Plan. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appServiceEnvironmentId` | string | `''` | | The Resource ID of the App Service Environment to use for the App Service Plan. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maximumElasticWorkerCount` | int | `1` | | Maximum number of total workers allowed for this ElasticScaleEnabled App Service Plan. | +| `perSiteScaling` | bool | `False` | | If true, apps assigned to this App Service plan can be scaled independently. If false, apps assigned to this App Service plan will scale to all instances of the plan. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `serverOS` | string | `'Windows'` | `[Windows, Linux]` | Kind of server OS. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `targetWorkerCount` | int | `0` | | Scaling worker count. | +| `targetWorkerSize` | int | `0` | `[0, 1, 2]` | The instance size of the hosting plan (small, medium, or large). | +| `workerTierName` | string | `''` | | Target worker tier assigned to the App Service plan. | + + +### Parameter Usage: `sku` + +```json +"sku": { + "value": { + "name": "P1v2", + "tier": "PremiumV2", + "size": "P1v2", + "family": "Pv2", + "capacity": 1 + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the app service plan | +| `resourceGroupName` | string | The resource group the app service plan was deployed into | +| `resourceId` | string | The resource ID of the app service plan | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Serverfarms](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-02-01/serverfarms) diff --git a/carml/1.0.1/Microsoft.Web/serverfarms/version.json b/carml/1.0.1/Microsoft.Web/serverfarms/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/serverfarms/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/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_components.bicep b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_components.bicep new file mode 100644 index 000000000..d9e7a6c98 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_components.bicep @@ -0,0 +1,81 @@ +@description('Required. Name of the application insights.') +param name string + +@description('Optional. Application type.') +@allowed([ + 'web' + 'other' +]) +param appInsightsType string = 'web' + +@description('Optional. Describes what tool created this app insights component. Customers using this API should set this to the default rest.') +@allowed([ + 'rest' +]) +param appInsightsRequestSource string = 'rest' + +@description('Required. Resource ID of the log analytics workspace which the data will be ingested to. This property is required to create an application with this API version. Applications from older versions will not have this property.') +param workspaceResourceId string + +@description('Optional. The network access type for accessing Application Insights ingestion. - Enabled or Disabled.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Optional. The network access type for accessing Application Insights query. - Enabled or Disabled.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Optional. The kind of application that this component refers to, used to customize UI. This value is a freeform string, values should typically be one of the following: web, ios, other, store, java, phone.') +param kind string = '' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +resource appInsights 'Microsoft.Insights/components@2020-02-02' = { + name: name + location: location + tags: tags + kind: kind + properties: { + Application_Type: appInsightsType + Request_Source: appInsightsRequestSource + WorkspaceResourceId: workspaceResourceId + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + } +} + +resource appInsights_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appInsights.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appInsights +} + +@description('The name of the application insights component.') +output name string = appInsights.name + +@description('The resource ID of the application insights component.') +output resourceId string = appInsights.id + +@description('The resource group the application insights component was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..517bc6038 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpointObj, 'name') ? (!empty(privateEndpointObj.name) ? privateEndpointObj.name : '${privateEndpointResourceName}-${privateEndpointObj.service}') : '${privateEndpointResourceName}-${privateEndpointObj.service}' + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (!empty(privateEndpointObj.privateDnsZoneResourceIds) ? privateEndpointObj.privateDnsZoneResourceIds : []) : [] + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (!empty(privateEndpointObj.customDnsConfigs) ? privateEndpointObj.customDnsConfigs : null) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..56956c1b9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') +} + +resource app 'Microsoft.Web/sites@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(app.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: app +}] diff --git a/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_serverfarms.bicep b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_serverfarms.bicep new file mode 100644 index 000000000..06d715a52 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.bicep/nested_serverfarms.bicep @@ -0,0 +1,88 @@ +@description('Required. The name of the app service plan to deploy.') +@minLength(1) +@maxLength(40) +param name string + +@description('Required. Defines the name, tier, size, family and capacity of the app service plan.') +param sku object + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Kind of server OS.') +@allowed([ + 'Windows' + 'Linux' +]) +param serverOS string = 'Windows' + +@description('Optional. The resource ID of the app service environment to use for this resource.') +param appServiceEnvironmentId string = '' + +@description('Optional. Target worker tier assigned to the app service plan.') +param workerTierName string = '' + +@description('Optional. If true, apps assigned to this app service plan can be scaled independently. If false, apps assigned to this app service plan will scale to all instances of the plan.') +param perSiteScaling bool = false + +@description('Optional. Maximum number of total workers allowed for this ElasticScaleEnabled app service plan.') +param maximumElasticWorkerCount int = 1 + +@description('Optional. Scaling worker count.') +param targetWorkerCount int = 0 + +@description('Optional. The instance size of the hosting plan (small, medium, or large).') +@allowed([ + 0 + 1 + 2 +]) +param targetWorkerSize int = 0 + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +resource appServicePlan 'Microsoft.Web/serverfarms@2021-02-01' = { + name: name + kind: serverOS == 'Windows' ? '' : 'linux' + location: location + tags: tags + sku: sku + properties: { + workerTierName: workerTierName + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? { + id: appServiceEnvironmentId + } : null + perSiteScaling: perSiteScaling + maximumElasticWorkerCount: maximumElasticWorkerCount + reserved: serverOS == 'Linux' + targetWorkerCount: targetWorkerCount + targetWorkerSizeId: targetWorkerSize + } +} + +resource appServicePlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appServicePlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appServicePlan +} + +@description('The name of the app service plan.') +output name string = appServicePlan.name + +@description('The resource ID of the app service plan.') +output resourceId string = appServicePlan.id + +@description('The resource group the app service plan was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Web/sites/.parameters/fa.min.parameters.json b/carml/1.0.1/Microsoft.Web/sites/.parameters/fa.min.parameters.json new file mode 100644 index 000000000..0d4b5e85f --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.parameters/fa.min.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fa-min-001" + }, + "kind": { + "value": "functionapp" + }, + "serverFarmResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + }, + "siteConfig": { + "value": { + "alwaysOn": true + } + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/sites/.parameters/fa.parameters.json b/carml/1.0.1/Microsoft.Web/sites/.parameters/fa.parameters.json new file mode 100644 index 000000000..01635aef5 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.parameters/fa.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": "<>-az-fa-x-001" + }, + "kind": { + "value": "functionapp" + }, + "serverFarmResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + }, + "appInsightId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001" + }, + "siteConfig": { + "value": { + "alwaysOn": true + } + }, + "storageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsafa001" + }, + "functionsWorkerRuntime": { + "value": "powershell" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/sites/.parameters/wa.min.parameters.json b/carml/1.0.1/Microsoft.Web/sites/.parameters/wa.min.parameters.json new file mode 100644 index 000000000..73cc95e2f --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.parameters/wa.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": { + "name": { + "value": "<>-az-wa-min-001" + }, + "kind": { + "value": "app" + }, + "serverFarmResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + }, + } +} diff --git a/carml/1.0.1/Microsoft.Web/sites/.parameters/wa.parameters.json b/carml/1.0.1/Microsoft.Web/sites/.parameters/wa.parameters.json new file mode 100644 index 000000000..9a4bdeeb9 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/.parameters/wa.parameters.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-wa-x-001" + }, + "kind": { + "value": "app" + }, + "serverFarmResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + }, + "appInsightObject": { + "value": { + "name": "<>-az-wa-x-001-appi", + "workspaceResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.OperationalInsights/workspaces/adp-<>-az-law-appi-001" + } + }, + "siteConfig": { + "value": { + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ], + "alwaysOn": true + } + }, + "httpsOnly": { + "value": true + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/sites/config/deploy.bicep b/carml/1.0.1/Microsoft.Web/sites/config/deploy.bicep new file mode 100644 index 000000000..d6fb05fd3 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/config/deploy.bicep @@ -0,0 +1,79 @@ +@description('Required. Name of the site config.') +@allowed([ + 'appsettings' +]) +param name string + +@description('Required. Name of the site parent resource.') +param appName string + +@description('Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions.') +param storageAccountId string = '' + +@description('Optional. Runtime of the function worker.') +@allowed([ + 'dotnet' + 'node' + 'python' + 'java' + 'powershell' + '' +]) +param functionsWorkerRuntime string = '' + +@description('Optional. Version of the function extension.') +param functionsExtensionVersion string = '~3' + +@description('Optional. Resource ID of the app insight to leverage for this resource.') +param appInsightId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource appInsight 'microsoft.insights/components@2020-02-02' existing = if (!empty(appInsightId)) { + name: last(split(appInsightId, '/')) + scope: resourceGroup(split(appInsightId, '/')[2], split(appInsightId, '/')[4]) +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' existing = if (!empty(storageAccountId)) { + name: last(split(storageAccountId, '/')) + scope: resourceGroup(split(storageAccountId, '/')[2], split(storageAccountId, '/')[4]) +} + +resource app 'Microsoft.Web/sites@2020-12-01' existing = { + name: appName +} + +resource config 'Microsoft.Web/sites/config@2021-02-01' = { + name: name + parent: app + properties: { + AzureWebJobsStorage: !empty(storageAccountId) ? 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' : any(null) + AzureWebJobsDashboard: !empty(storageAccountId) ? 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};' : any(null) + FUNCTIONS_EXTENSION_VERSION: app.kind == 'functionapp' && !empty(functionsExtensionVersion) ? functionsExtensionVersion : any(null) + FUNCTIONS_WORKER_RUNTIME: app.kind == 'functionapp' && !empty(functionsWorkerRuntime) ? functionsWorkerRuntime : any(null) + APPINSIGHTS_INSTRUMENTATIONKEY: !empty(appInsightId) ? appInsight.properties.InstrumentationKey : '' + APPLICATIONINSIGHTS_CONNECTION_STRING: !empty(appInsightId) ? appInsight.properties.ConnectionString : '' + } +} + +@description('The name of the site config.') +output name string = config.name + +@description('The resource ID of the site config.') +output resourceId string = config.id + +@description('The resource group the site config was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/Microsoft.Web/sites/config/readme.md b/carml/1.0.1/Microsoft.Web/sites/config/readme.md new file mode 100644 index 000000000..5f6a31608 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/config/readme.md @@ -0,0 +1,46 @@ +# Web Site Config `[Microsoft.Web/sites/config]` + +This module deploys a site config resource. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Web/sites/config` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `appName` | string | | Name of the site parent resource. | +| `name` | string | `[appsettings]` | Name of the site config. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appInsightId` | string | `''` | | Resource ID of the app insight to leverage for this resource. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `functionsExtensionVersion` | string | `'~3'` | | Version of the function extension. | +| `functionsWorkerRuntime` | string | `''` | `[dotnet, node, python, java, powershell, ]` | Runtime of the function worker. | +| `storageAccountId` | string | `''` | | Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the site config. | +| `resourceGroupName` | string | The resource group the site config was deployed into. | +| `resourceId` | string | The resource ID of the site config. | + +## Template references + +- ['sites/config' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) diff --git a/carml/1.0.1/Microsoft.Web/sites/config/version.json b/carml/1.0.1/Microsoft.Web/sites/config/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/config/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/carml/1.0.1/Microsoft.Web/sites/deploy.bicep b/carml/1.0.1/Microsoft.Web/sites/deploy.bicep new file mode 100644 index 000000000..1e04075ae --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/deploy.bicep @@ -0,0 +1,258 @@ +@description('Required. Name of the site.') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Required. Type of site to deploy.') +@allowed([ + 'functionapp' + 'app' +]) +param kind string + +@description('Optional. Configures a site to accept only HTTPS requests. Issues redirect for HTTP requests.') +param httpsOnly bool = true + +@description('Optional. If client affinity is enabled.') +param clientAffinityEnabled bool = true + +@description('Optional. Configuration of the app.') +param siteConfig object = {} + +@description('Optional. Required if functionapp kind. The resource ID of the storage account to manage triggers and logging function executions.') +param storageAccountId string = '' + +@description('Optional. Runtime of the function worker.') +@allowed([ + 'dotnet' + 'node' + 'python' + 'java' + 'powershell' + '' +]) +param functionsWorkerRuntime string = '' + +@description('Optional. Version if the function extension.') +param functionsExtensionVersion string = '~3' + +@description('Optional. The resource ID of the app service plan to use for the site.') +param serverFarmResourceId string = '' + +@description('Optional. The resource ID of the existing app insight to leverage for the app. If the resource ID is not provided, the appInsightObject can be used to create a new app insight.') +param appInsightId string = '' + +@description('Optional. Used to deploy a new app insight if no appInsightId is provided.') +param appInsightObject object = {} + +@description('Optional. The resource ID of the app service environment to use for this resource.') +param appServiceEnvironmentId string = '' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Configuration details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AppServiceHTTPLogs' + 'AppServiceConsoleLogs' + 'AppServiceAppLogs' + 'AppServiceAuditLogs' + 'AppServiceIPSecAuditLogs' + 'AppServicePlatformLogs' + 'FunctionAppLogs' +]) +param diagnosticLogCategoriesToEnable array = kind == 'functionapp' ? [ + 'FunctionAppLogs' +] : [ + 'AppServiceHTTPLogs' + 'AppServiceConsoleLogs' + 'AppServiceAppLogs' + 'AppServiceAuditLogs' + 'AppServiceIPSecAuditLogs' + 'AppServicePlatformLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module appInsight '.bicep/nested_components.bicep' = if (!empty(appInsightObject)) { + name: '${uniqueString(deployment().name, location)}-Site-AppInsight' + params: { + name: contains(appInsightObject, 'name') ? !empty(appInsightObject.name) ? appInsightObject.name : '${name}-appi' : '${name}-appi' + workspaceResourceId: appInsightObject.workspaceResourceId + tags: tags + lock: lock + location: location + } +} + +resource app 'Microsoft.Web/sites@2020-12-01' = { + name: name + location: location + kind: kind + tags: tags + identity: identity + properties: { + serverFarmId: serverFarmResourceId + httpsOnly: httpsOnly + hostingEnvironmentProfile: !empty(appServiceEnvironmentId) ? { + id: appServiceEnvironmentId + } : null + clientAffinityEnabled: clientAffinityEnabled + siteConfig: siteConfig + } +} + +module app_appsettings 'config/deploy.bicep' = { + name: '${uniqueString(deployment().name, location)}-Site-Config' + params: { + name: 'appsettings' + appName: app.name + storageAccountId: !empty(storageAccountId) ? storageAccountId : '' + appInsightId: !empty(appInsightId) ? appInsightId : !empty(appInsightObject) ? appInsight.outputs.resourceId : '' + functionsWorkerRuntime: !empty(functionsWorkerRuntime) ? functionsWorkerRuntime : '' + functionsExtensionVersion: !empty(functionsExtensionVersion) ? functionsExtensionVersion : '~3' + } +} + +resource app_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${app.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: app +} + +resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: app +} + +module app_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Site-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: app.id + } +}] + +module app_privateEndpoint '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-Site-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: app.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The name of the site.') +output name string = app.name + +@description('The resource ID of the site.') +output resourceId string = app.id + +@description('The resource group the site was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(app.identity, 'principalId') ? app.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Web/sites/readme.md b/carml/1.0.1/Microsoft.Web/sites/readme.md new file mode 100644 index 000000000..f35975e3c --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/readme.md @@ -0,0 +1,174 @@ +# Web/Function Apps `[Microsoft.Web/sites]` + +This module deploys a web or function app. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/components` | 2020-02-02 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.Web/sites` | 2020-12-01 | +| `Microsoft.Web/sites/config` | 2021-02-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `kind` | string | `[functionapp, app]` | Type of site to deploy. | +| `name` | string | | Name of the site. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `appInsightId` | string | `''` | | The resource ID of the existing app insight to leverage for the app. If the resource ID is not provided, the appInsightObject can be used to create a new app insight. | +| `appInsightObject` | object | `{object}` | | Used to deploy a new app insight if no appInsightId is provided. | +| `appServiceEnvironmentId` | string | `''` | | The resource ID of the app service environment to use for this resource. | +| `clientAffinityEnabled` | bool | `True` | | If client affinity is enabled. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[if(equals(parameters('kind'), 'functionapp'), createArray('FunctionAppLogs'), createArray('AppServiceHTTPLogs', 'AppServiceConsoleLogs', 'AppServiceAppLogs', 'AppServiceAuditLogs', 'AppServiceIPSecAuditLogs', 'AppServicePlatformLogs'))]` | `[AppServiceHTTPLogs, AppServiceConsoleLogs, AppServiceAppLogs, AppServiceAuditLogs, AppServiceIPSecAuditLogs, AppServicePlatformLogs, FunctionAppLogs]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `functionsExtensionVersion` | string | `'~3'` | | Version if the function extension. | +| `functionsWorkerRuntime` | string | `''` | `[dotnet, node, python, java, powershell, ]` | Runtime of the function worker. | +| `httpsOnly` | bool | `True` | | Configures a site to accept only HTTPS requests. Issues redirect for HTTP requests. | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration details for private endpoints. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `serverFarmResourceId` | string | `''` | | The resource ID of the app service plan to use for the site. | +| `siteConfig` | object | `{object}` | | Configuration of the app. | +| `storageAccountId` | string | `''` | | Required if functionapp kind. The resource ID of the storage account to manage triggers and logging function executions. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the site. | +| `resourceGroupName` | string | The resource group the site was deployed into. | +| `resourceId` | string | The resource ID of the site. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- ['sites/config' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/sites) +- [Components](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2020-02-02/components) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Sites](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2020-12-01/sites) diff --git a/carml/1.0.1/Microsoft.Web/sites/version.json b/carml/1.0.1/Microsoft.Web/sites/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/sites/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/carml/1.0.1/Microsoft.Web/staticSites/.bicep/nested_privateEndpoint.bicep b/carml/1.0.1/Microsoft.Web/staticSites/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..517bc6038 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: contains(privateEndpointObj, 'name') ? (!empty(privateEndpointObj.name) ? privateEndpointObj.name : '${privateEndpointResourceName}-${privateEndpointObj.service}') : '${privateEndpointResourceName}-${privateEndpointObj.service}' + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (!empty(privateEndpointObj.privateDnsZoneResourceIds) ? privateEndpointObj.privateDnsZoneResourceIds : []) : [] + customDnsConfigs: contains(privateEndpointObj, 'customDnsConfigs') ? (!empty(privateEndpointObj.customDnsConfigs) ? privateEndpointObj.customDnsConfigs : null) : null +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } +} diff --git a/carml/1.0.1/Microsoft.Web/staticSites/.bicep/nested_rbac.bicep b/carml/1.0.1/Microsoft.Web/staticSites/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b7e58fdec --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param principalType string = '' +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource staticSite 'Microsoft.Web/staticSites@2021-02-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(staticSite.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: staticSite +}] diff --git a/carml/1.0.1/Microsoft.Web/staticSites/.parameters/min.parameters.json b/carml/1.0.1/Microsoft.Web/staticSites/.parameters/min.parameters.json new file mode 100644 index 000000000..b5781f46f --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-wss-min-001" + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/staticSites/.parameters/parameters.json b/carml/1.0.1/Microsoft.Web/staticSites/.parameters/parameters.json new file mode 100644 index 000000000..46d43ca75 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/.parameters/parameters.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-wss-x-001" + }, + "sku": { + "value": "Standard" + }, + "stagingEnvironmentPolicy": { + "value": "Enabled" + }, + "allowConfigFileUpdates": { + "value": true + }, + "enterpriseGradeCdnStatus": { + "value": "Disabled" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "staticSites" + } + ] + } + } +} diff --git a/carml/1.0.1/Microsoft.Web/staticSites/deploy.bicep b/carml/1.0.1/Microsoft.Web/staticSites/deploy.bicep new file mode 100644 index 000000000..731c02afd --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/deploy.bicep @@ -0,0 +1,159 @@ +@description('Required. Name of the static site.') +@minLength(1) +@maxLength(40) +param name string + +@allowed([ + 'Free' + 'Standard' +]) +@description('Optional. Type of static site to deploy.') +param sku string = 'Free' + +@description('Optional. If config file is locked for this static web app.') +param allowConfigFileUpdates bool = true + +@description('Optional. Location to deploy static site. The following locations are supported: CentralUS, EastUS2, EastAsia, WestEurope, WestUS2') +param location string = resourceGroup().location + +@allowed([ + 'Enabled' + 'Disabled' +]) +@description('Optional. State indicating whether staging environments are allowed or not allowed for a static web app.') +param stagingEnvironmentPolicy string = 'Enabled' + +@allowed([ + 'Disabled' + 'Disabling' + 'Enabled' + 'Enabling' +]) +@description('Optional. State indicating the status of the enterprise grade CDN serving traffic to the static web app.') +param enterpriseGradeCdnStatus string = 'Disabled' + +@description('Optional. Build properties for the static site.') +param buildProperties object = {} + +@description('Optional. Template Options for the static site.') +param templateProperties object = {} + +@description('Optional. The provider that submitted the last deployment to the primary environment of the static site.') +param provider string = 'None' + +@secure() +@description('Optional. The Personal Access Token for accessing the GitHub repo.') +param repositoryToken string = '' + +@description('Optional. The name of the GitHub repo.') +param repositoryUrl string = '' + +@description('Optional. The branch name of the GitHub repo.') +param branch string = '' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Configuration details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource staticSite 'Microsoft.Web/staticSites@2021-03-01' = { + name: name + location: location + tags: tags + identity: identity + sku: { + name: sku + tier: sku + } + properties: { + allowConfigFileUpdates: allowConfigFileUpdates + stagingEnvironmentPolicy: stagingEnvironmentPolicy + enterpriseGradeCdnStatus: enterpriseGradeCdnStatus + provider: !empty(provider) ? provider : 'None' + branch: !empty(branch) ? branch : null + buildProperties: !empty(buildProperties) ? buildProperties : null + repositoryToken: !empty(repositoryToken) ? repositoryToken : null + repositoryUrl: !empty(repositoryUrl) ? repositoryUrl : null + templateProperties: !empty(templateProperties) ? templateProperties : null + } +} + +resource staticSite_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${staticSite.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: staticSite +} + +module staticSite_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-StaticSite-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: staticSite.id + } +}] + +module staticSite_privateEndpoint '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-StaticSite-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: staticSite.id + privateEndpointVnetLocation: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +@description('The name of the static site.') +output name string = staticSite.name + +@description('The resource ID of the static site.') +output resourceId string = staticSite.id + +@description('The resource group the static site was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(staticSite.identity, 'principalId') ? staticSite.identity.principalId : '' diff --git a/carml/1.0.1/Microsoft.Web/staticSites/readme.md b/carml/1.0.1/Microsoft.Web/staticSites/readme.md new file mode 100644 index 000000000..09f9a7436 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/readme.md @@ -0,0 +1,193 @@ +# Static Web Sites `[Microsoft.Web/staticSites]` + +This module deploys a Static Web Site. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | +| `Microsoft.Web/staticSites` | 2021-03-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the static site. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowConfigFileUpdates` | bool | `True` | | If config file is locked for this static web app. | +| `branch` | string | `''` | | The branch name of the GitHub repo. | +| `buildProperties` | object | `{object}` | | Build properties for the static site. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enterpriseGradeCdnStatus` | string | `'Disabled'` | `[Disabled, Disabling, Enabled, Enabling]` | State indicating the status of the enterprise grade CDN serving traffic to the static web app. | +| `location` | string | `[resourceGroup().location]` | | Location to deploy static site. The following locations are supported: CentralUS, EastUS2, EastAsia, WestEurope, WestUS2 | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateEndpoints` | array | `[]` | | Configuration details for private endpoints. | +| `provider` | string | `'None'` | | The provider that submitted the last deployment to the primary environment of the static site. | +| `repositoryToken` | secureString | `''` | | The Personal Access Token for accessing the GitHub repo. | +| `repositoryUrl` | string | `''` | | The name of the GitHub repo. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `sku` | string | `'Free'` | `[Free, Standard]` | Type of static site to deploy. | +| `stagingEnvironmentPolicy` | string | `'Enabled'` | `[Enabled, Disabled]` | State indicating whether staging environments are allowed or not allowed for a static web app. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `templateProperties` | object | `{object}` | | Template Options for the static site. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + + +### Parameter Usage: `buildProperties` + +[StaticSiteBuildProperties - Microsoft.Web/staticSites 2021-03-01 - Bicep & ARM template reference | Microsoft Docs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-03-01/staticSites?tabs=bicep#staticsitebuildproperties) + +```bicep + buildProperties: { + apiBuildCommand: 'string' + apiLocation: 'string' + appArtifactLocation: 'string' + appBuildCommand: 'string' + appLocation: 'string' + githubActionSecretNameOverride: 'string' + outputLocation: 'string' + skipGithubActionWorkflowGeneration: bool + } +``` + +### Parameter Usage: `templateProperties` + +[StaticSiteTemplateOptions - Microsoft.Web/staticSites 2021-03-01 - Bicep & ARM template reference | Microsoft Docs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-03-01/staticSites?tabs=bicep#staticsitetemplateoptions) + +```bicep + buildProperties: { + apiBuildCommand: 'string' + apiLocation: 'string' + appArtifactLocation: 'string' + appBuildCommand: 'string' + appLocation: 'string' + githubActionSecretNameOverride: 'string' + outputLocation: 'string' + skipGithubActionWorkflowGeneration: bool + } +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the static site. | +| `resourceGroupName` | string | The resource group the static site was deployed into. | +| `resourceId` | string | The resource ID of the static site. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Staticsites](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Web/2021-03-01/staticSites) diff --git a/carml/1.0.1/Microsoft.Web/staticSites/version.json b/carml/1.0.1/Microsoft.Web/staticSites/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.0.1/Microsoft.Web/staticSites/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.0.1/README.md b/carml/1.0.1/README.md new file mode 100644 index 000000000..3afe8fdc3 --- /dev/null +++ b/carml/1.0.1/README.md @@ -0,0 +1,102 @@ +In this section you can find useful information regarding the Modules that are contained in this repository. + +## Available Resource Modules + +| Name | Provider namespace | Resource Type | +| - | - | - | +| [Azure Active Directory Domain Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AAD/DomainServices) | `MS.AAD` | [DomainServices](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AAD/DomainServices) | +| [Analysis Services Servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AnalysisServices/servers) | `MS.AnalysisServices` | [servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.AnalysisServices/servers) | +| [API Management Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ApiManagement/service) | `MS.ApiManagement` | [service](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ApiManagement/service) | +| [Policy Assignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyAssignments) | `MS.Authorization` | [policyAssignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyAssignments) | +| [Policy Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyDefinitions) | | [policyDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyDefinitions) | +| [Policy Exemptions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyExemptions) | | [policyExemptions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policyExemptions) | +| [Policy Set Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policySetDefinitions) | | [policySetDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/policySetDefinitions) | +| [Role Assignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleAssignments) | | [roleAssignments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleAssignments) | +| [Role Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleDefinitions) | | [roleDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Authorization/roleDefinitions) | +| [Automation Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Automation/automationAccounts) | `MS.Automation` | [automationAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Automation/automationAccounts) | +| [Batch Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Batch/batchAccounts) | `MS.Batch` | [batchAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Batch/batchAccounts) | +| [Cognitive Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.CognitiveServices/accounts) | `MS.CognitiveServices` | [accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.CognitiveServices/accounts) | +| [Availability Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/availabilitySets) | `MS.Compute` | [availabilitySets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/availabilitySets) | +| [Disk Encryption Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/diskEncryptionSets) | | [diskEncryptionSets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/diskEncryptionSets) | +| [Compute Disks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/disks) | | [disks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/disks) | +| [Azure Compute Galleries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/galleries) | | [galleries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/galleries) | +| [Images](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/images) | | [images](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/images) | +| [Proximity Placement Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/proximityPlacementGroups) | | [proximityPlacementGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/proximityPlacementGroups) | +| [Virtual Machines](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachines) | | [virtualMachines](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachines) | +| [Virtual Machine Scale Sets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachineScaleSets) | | [virtualMachineScaleSets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Compute/virtualMachineScaleSets) | +| [Budgets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Consumption/budgets) | `MS.Consumption` | [budgets](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Consumption/budgets) | +| [Container Instances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerInstance/containerGroups) | `MS.ContainerInstance` | [containerGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerInstance/containerGroups) | +| [Container Registries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerRegistry/registries) | `MS.ContainerRegistry` | [registries](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerRegistry/registries) | +| [Azure Kubernetes Services](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerService/managedClusters) | `MS.ContainerService` | [managedClusters](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ContainerService/managedClusters) | +| [Azure Databricks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Databricks/workspaces) | `MS.Databricks` | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Databricks/workspaces) | +| [Data Factories](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DataFactory/factories) | `MS.DataFactory` | [factories](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DataFactory/factories) | +| [AVD Application Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/applicationgroups) | `MS.DesktopVirtualization` | [applicationgroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/applicationgroups) | +| [AVD Host Pools](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/hostpools) | | [hostpools](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/hostpools) | +| [AVD Scaling Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/scalingplans) | | [scalingplans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/scalingplans) | +| [AVD Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/workspaces) | | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DesktopVirtualization/workspaces) | +| [DocumentDB Database Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DocumentDB/databaseAccounts) | `MS.DocumentDB` | [databaseAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.DocumentDB/databaseAccounts) | +| [Event Grid System Topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/systemTopics) | `MS.EventGrid` | [systemTopics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/systemTopics) | +| [Event Grid Topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/topics) | | [topics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventGrid/topics) | +| [Event Hub Namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventHub/namespaces) | `MS.EventHub` | [namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.EventHub/namespaces) | +| [Azure Health Bots](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.HealthBot/healthBots) | `MS.HealthBot` | [healthBots](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.HealthBot/healthBots) | +| [Action Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/actionGroups) | `MS.Insights` | [actionGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/actionGroups) | +| [Activity Log Alerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/activityLogAlerts) | | [activityLogAlerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/activityLogAlerts) | +| [Application Insights](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/components) | | [components](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/components) | +| [Activity Logs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/diagnosticSettings) | | [diagnosticSettings](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/diagnosticSettings) | +| [Metric Alerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/metricAlerts) | | [metricAlerts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/metricAlerts) | +| [Azure Monitor Private Link Scopes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/privateLinkScopes) | | [privateLinkScopes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/privateLinkScopes) | +| [Scheduled Query Rules](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/scheduledQueryRules) | | [scheduledQueryRules](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Insights/scheduledQueryRules) | +| [Key Vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KeyVault/vaults) | `MS.KeyVault` | [vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KeyVault/vaults) | +| [Kubernetes Configuration Extensions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KubernetesConfiguration/extensions) | `MS.KubernetesConfiguration` | [extensions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KubernetesConfiguration/extensions) | +| [Kubernetes Configuration Flux Configurations](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KubernetesConfiguration/fluxConfigurations) | | [fluxConfigurations](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.KubernetesConfiguration/fluxConfigurations) | +| [Logic Apps](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Logic/workflows) | `MS.Logic` | [workflows](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Logic/workflows) | +| [Machine Learning Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.MachineLearningServices/workspaces) | `MS.achineLearningServices` | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.MachineLearningServices/workspaces) | +| [User Assigned Identities](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedIdentity/userAssignedIdentities) | `MS.anagedIdentity` | [userAssignedIdentities](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedIdentity/userAssignedIdentities) | +| [Registration Definitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedServices/registrationDefinitions) | `MS.anagedServices` | [registrationDefinitions](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ManagedServices/registrationDefinitions) | +| [Management Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Management/managementGroups) | `MS.anagement` | [managementGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Management/managementGroups) | +| [Azure NetApp Files](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.NetApp/netAppAccounts) | `MS.NetApp` | [netAppAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.NetApp/netAppAccounts) | +| [Network Application Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationGateways) | `MS.Network` | [applicationGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationGateways) | +| [Application Security Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationSecurityGroups) | | [applicationSecurityGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/applicationSecurityGroups) | +| [Azure Firewalls](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/azureFirewalls) | | [azureFirewalls](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/azureFirewalls) | +| [Bastion Hosts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/bastionHosts) | | [bastionHosts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/bastionHosts) | +| [Virtual Network Gateway Connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/connections) | | [connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/connections) | +| [DDoS Protection Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ddosProtectionPlans) | | [ddosProtectionPlans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ddosProtectionPlans) | +| [ExpressRoute Circuits](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/expressRouteCircuits) | | [expressRouteCircuits](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/expressRouteCircuits) | +| [Firewall Policies](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/firewallPolicies) | | [firewallPolicies](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/firewallPolicies) | +| [Front Doors](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/frontDoors) | | [frontDoors](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/frontDoors) | +| [IP Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ipGroups) | | [ipGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/ipGroups) | +| [Load Balancers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/loadBalancers) | | [loadBalancers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/loadBalancers) | +| [Local Network Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/localNetworkGateways) | | [localNetworkGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/localNetworkGateways) | +| [NAT Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/natGateways) | | [natGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/natGateways) | +| [Network Security Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkSecurityGroups) | | [networkSecurityGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkSecurityGroups) | +| [Network Watchers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkWatchers) | | [networkWatchers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/networkWatchers) | +| [Private DNS Zones](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateDnsZones) | | [privateDnsZones](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateDnsZones) | +| [Private Endpoints](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateEndpoints) | | [privateEndpoints](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/privateEndpoints) | +| [Public IP Addresses](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPAddresses) | | [publicIPAddresses](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPAddresses) | +| [Public IP Prefixes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPPrefixes) | | [publicIPPrefixes](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/publicIPPrefixes) | +| [Route Tables](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/routeTables) | | [routeTables](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/routeTables) | +| [Traffic Manager Profiles](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/trafficmanagerprofiles) | | [trafficmanagerprofiles](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/trafficmanagerprofiles) | +| [Virtual Hubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualHubs) | | [virtualHubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualHubs) | +| [Virtual Network Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworkGateways) | | [virtualNetworkGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworkGateways) | +| [Virtual Networks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworks) | | [virtualNetworks](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualNetworks) | +| [Virtual WANs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualWans) | | [virtualWans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/virtualWans) | +| [VPN Gateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/vpnGateways) | | [vpnGateways](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/vpnGateways) | +| [VPN Sites](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/vpnSites) | | [vpnSites](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Network/vpnSites) | +| [Log Analytics Workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.OperationalInsights/workspaces) | `MS.OperationalInsights` | [workspaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.OperationalInsights/workspaces) | +| [Recovery Services Vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.RecoveryServices/vaults) | `MS.RecoveryServices` | [vaults](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.RecoveryServices/vaults) | +| [Deployment Scripts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/deploymentScripts) | `MS.Resources` | [deploymentScripts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/deploymentScripts) | +| [Resource Groups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/resourceGroups) | | [resourceGroups](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/resourceGroups) | +| [Resources Tags](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/tags) | | [tags](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Resources/tags) | +| [Azure Security Center](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Security/azureSecurityCenter) | `MS.Security` | [azureSecurityCenter](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Security/azureSecurityCenter) | +| [Service Bus Namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceBus/namespaces) | `MS.ServiceBus` | [namespaces](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceBus/namespaces) | +| [Service Fabric Clusters](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceFabric/clusters) | `MS.ServiceFabric` | [clusters](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.ServiceFabric/clusters) | +| [SQL Managed Instances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/managedInstances) | `MS.Sql` | [managedInstances](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/managedInstances) | +| [SQL Servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/servers) | | [servers](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Sql/servers) | +| [Storage Accounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Storage/storageAccounts) | `MS.Storage` | [storageAccounts](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Storage/storageAccounts) | +| [Azure Synapse Analytics](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Synapse/privateLinkHubs) | `MS.Synapse` | [privateLinkHubs](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Synapse/privateLinkHubs) | +| [Image Templates](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.VirtualMachineImages/imageTemplates) | `MS.VirtualMachineImages` | [imageTemplates](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.VirtualMachineImages/imageTemplates) | +| [API Connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/connections) | `MS.Web` | [connections](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/connections) | +| [App Service Environments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/hostingEnvironments) | | [hostingEnvironments](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/hostingEnvironments) | +| [App Service Plans](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/serverfarms) | | [serverfarms](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/serverfarms) | +| [Web/Function Apps](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/sites) | | [sites](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/sites) | +| [Static Web Sites](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/staticSites) | | [staticSites](https://github.com/Azure/ResourceModules/tree/main/arm/Microsoft.Web/staticSites) | diff --git a/carml/1.0.1/service/.bicep/nested_authorizationServers.bicep b/carml/1.0.1/service/.bicep/nested_authorizationServers.bicep new file mode 100644 index 000000000..8bbf63802 --- /dev/null +++ b/carml/1.0.1/service/.bicep/nested_authorizationServers.bicep @@ -0,0 +1,116 @@ +@description('Required. Identifier of the authorization server.') +param name string + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. OAuth authorization endpoint. See .') +param authorizationEndpoint string + +@description('Optional. HTTP verbs supported by the authorization endpoint. GET must be always present. POST is optional. - HEAD, OPTIONS, TRACE, GET, POST, PUT, PATCH, DELETE') +param authorizationMethods array = [ + 'GET' +] + +@description('Optional. Specifies the mechanism by which access token is passed to the API. - authorizationHeader or query') +param bearerTokenSendingMethods array = [ + 'authorizationHeader' +] + +@description('Optional. Method of authentication supported by the token endpoint of this authorization server. Possible values are Basic and/or Body. When Body is specified, client credentials and other parameters are passed within the request body in the application/x-www-form-urlencoded format. - Basic or Body') +param clientAuthenticationMethod array = [ + 'Basic' +] + +@description('Optional. Optional reference to a page where client or app registration for this authorization server is performed. Contains absolute URL to entity being referenced.') +param clientRegistrationEndpoint string = '' + +@description('Required. Name of the key vault that stores clientId and clientSecret for this authorization server.') +param clientCredentialsKeyVaultId string + +@description('Required. Name of the secret that stores the Client or app ID registered with this authorization server.') +param clientIdSecretName string + +@description('Required. Name of the secret that stores the Client or app secret registered with this authorization server. This property will not be filled on \'GET\' operations! Use \'/listSecrets\' POST request to get the value.') +param clientSecretSecretName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Access token scope that is going to be requested by default. Can be overridden at the API level. Should be provided in the form of a string containing space-delimited values.') +param defaultScope string = '' + +@description('Optional. Description of the authorization server. Can contain HTML formatting tags.') +param serverDescription string = '' + +@description('Required. Form of an authorization grant, which the client uses to request the access token. - authorizationCode, implicit, resourceOwnerPassword, clientCredentials') +param grantTypes array + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner password.') +param resourceOwnerPassword string = '' + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner username.') +param resourceOwnerUsername string = '' + +@description('Optional. If true, authorization server will include state parameter from the authorization request to its response. Client may use state parameter to raise protocol security.') +param supportState bool = false + +@description('Optional. Additional parameters required by the token endpoint of this authorization server represented as an array of JSON objects with name and value string properties, i.e. {"name" : "name value", "value": "a value"}. - TokenBodyParameterContract object') +param tokenBodyParameters array = [] + +@description('Optional. OAuth token endpoint. Contains absolute URI to entity being referenced.') +param tokenEndpoint string = '' + +var defaultAuthorizationMethods = [ + 'GET' +] +var setAuthorizationMethods = union(authorizationMethods, defaultAuthorizationMethods) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' existing = { + name: last(split(clientCredentialsKeyVaultId, '/')) + scope: resourceGroup(split(clientCredentialsKeyVaultId, '/')[2], split(clientCredentialsKeyVaultId, '/')[4]) +} + +module authorizationServer '../authorizationServers/deploy.bicep' = { + name: '${deployment().name}-AuthorizationServer' + params: { + apiManagementServiceName: apiManagementServiceName + serverDescription: serverDescription + authorizationMethods: setAuthorizationMethods + clientAuthenticationMethod: clientAuthenticationMethod + tokenBodyParameters: tokenBodyParameters + tokenEndpoint: tokenEndpoint + supportState: supportState + defaultScope: defaultScope + bearerTokenSendingMethods: bearerTokenSendingMethods + resourceOwnerUsername: resourceOwnerUsername + resourceOwnerPassword: resourceOwnerPassword + name: name + clientRegistrationEndpoint: clientRegistrationEndpoint + authorizationEndpoint: authorizationEndpoint + grantTypes: grantTypes + clientId: keyVault.getSecret(clientIdSecretName) + clientSecret: keyVault.getSecret(clientSecretSecretName) + } +} + +@description('The name of the API management service authorization server') +output name string = authorizationServer.outputs.name + +@description('The resource ID of the API management service authorization server') +output resourceId string = authorizationServer.outputs.resourceId + +@description('The resource group the API management service authorization server was deployed into') +output resourceGroupName string = authorizationServer.outputs.resourceGroupName diff --git a/carml/1.0.1/service/.bicep/nested_rbac.bicep b/carml/1.0.1/service/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..01dfeb05f --- /dev/null +++ b/carml/1.0.1/service/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'API Management Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c') + 'API Management Service Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61') + 'API Management Service Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource service 'Microsoft.ApiManagement/service@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(service.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: service +}] diff --git a/carml/1.0.1/service/.parameters/max.parameters.json b/carml/1.0.1/service/.parameters/max.parameters.json new file mode 100644 index 000000000..6e0aa4c38 --- /dev/null +++ b/carml/1.0.1/service/.parameters/max.parameters.json @@ -0,0 +1,174 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apim-max-001" + }, + "publisherEmail": { + "value": "apimgmt-noreply@mail.windowsazure.com" + }, + "publisherName": { + "value": "<>-az-amorg-x-001" + }, + "apis": { + "value": [ + { + "name": "echo-api", + "displayName": "Echo API", + "path": "echo", + "serviceUrl": "http://echoapi.cloudapp.net/api", + "apiVersionSet": { + "name": "echo-version-set", + "properties": { + "description": "echo-version-set", + "displayName": "echo-version-set", + "versioningScheme": "Segment" + } + } + } + ] + }, + "authorizationServers": { + "value": [ + { + "name": "AuthServer1", + "authorizationEndpoint": "https://login.microsoftonline.com/651b43ce-ccb8-4301-b551-b04dd872d401/oauth2/v2.0/authorize", + "grantTypes": [ + "authorizationCode" + ], + "clientCredentialsKeyVaultId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "clientIdSecretName": "apimclientid", + "clientSecretSecretName": "apimclientsecret", + "clientRegistrationEndpoint": "http://localhost", + "tokenEndpoint": "https://login.microsoftonline.com/651b43ce-ccb8-4301-b551-b04dd872d401/oauth2/v2.0/token" + } + ] + }, + "backends": { + "value": [ + { + "name": "backend", + "url": "http://echoapi.cloudapp.net/api", + "tls": { + "validateCertificateChain": false, + "validateCertificateName": false + } + } + ] + }, + "caches": { + "value": [ + { + "name": "westeurope", + "connectionString": "connectionstringtest", + "useFromLocation": "westeurope" + } + ] + }, + "identityProviders": { + "value": [ + { + "name": "aadProvider" + } + ] + }, + "namedValues": { + "value": [ + { + "name": "apimkey", + "displayName": "apimkey", + "secret": true + } + ] + }, + "policies": { + "value": [ + { + "value": " ", + "format": "xml" + } + ] + }, + "portalSettings": { + "value": [ + { + "name": "signin", + "properties": { + "enabled": false + } + }, + { + "name": "signup", + "properties": { + "enabled": false, + "termsOfService": { + "enabled": false, + "consentRequired": false + } + } + } + ] + }, + "products": { + "value": [ + { + "name": "Starter", + "subscriptionRequired": false, + "approvalRequired": false, + "apis": [ + { + "name": "echo-api" + } + ], + "groups": [ + { + "name": "developers" + } + ] + } + ] + }, + "subscriptions": { + "value": [ + { + "scope": "/apis", + "name": "testArmSubscriptionAllApis" + } + ] + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.0.1/service/.parameters/min.parameters.json b/carml/1.0.1/service/.parameters/min.parameters.json new file mode 100644 index 000000000..61b0c615a --- /dev/null +++ b/carml/1.0.1/service/.parameters/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": { + "name": { + "value": "<>-az-apim-min-001" + }, + "publisherEmail": { + "value": "apimgmt-noreply@mail.windowsazure.com" + }, + "publisherName": { + "value": "<>-az-amorg-x-001" + } + } +} \ No newline at end of file diff --git a/carml/1.0.1/service/.parameters/parameters.json b/carml/1.0.1/service/.parameters/parameters.json new file mode 100644 index 000000000..4cf5e8349 --- /dev/null +++ b/carml/1.0.1/service/.parameters/parameters.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apim-x-001" + }, + "publisherEmail": { + "value": "apimgmt-noreply@mail.windowsazure.com" + }, + "publisherName": { + "value": "<>-az-amorg-x-001" + }, + "portalSettings": { + "value": [ + { + "name": "signin", + "properties": { + "enabled": false + } + }, + { + "name": "signup", + "properties": { + "enabled": false, + "termsOfService": { + "enabled": false, + "consentRequired": false + } + } + } + ] + }, + "policies": { + "value": [ + { + "value": " ", + "format": "xml" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.0.1/service/apiVersionSets/deploy.bicep b/carml/1.0.1/service/apiVersionSets/deploy.bicep new file mode 100644 index 000000000..038302e85 --- /dev/null +++ b/carml/1.0.1/service/apiVersionSets/deploy.bicep @@ -0,0 +1,42 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. API Version set name') +param name string = 'default' + +@description('Optional. API Version set properties') +param properties object = {} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource apiVersionSet 'Microsoft.ApiManagement/service/apiVersionSets@2021-08-01' = { + name: name + parent: service + properties: properties +} + +@description('The resource ID of the API Version set') +output resourceId string = apiVersionSet.id + +@description('The name of the API Version set') +output name string = apiVersionSet.name + +@description('The resource group the API Version set was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/apiVersionSets/readme.md b/carml/1.0.1/service/apiVersionSets/readme.md new file mode 100644 index 000000000..6bd9d2496 --- /dev/null +++ b/carml/1.0.1/service/apiVersionSets/readme.md @@ -0,0 +1,43 @@ +# API Management Service API Version Sets `[Microsoft.ApiManagement/service/apiVersionSets]` + +This module deploys API Management Service APIs Version Set. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/apiVersionSets` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | API Version set name | +| `properties` | object | `{object}` | API Version set properties | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API Version set | +| `resourceGroupName` | string | The resource group the API Version set was deployed into | +| `resourceId` | string | The resource ID of the API Version set | + +## Template references + +- [Service/Apiversionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apiVersionSets) diff --git a/carml/1.0.1/service/apiVersionSets/version.json b/carml/1.0.1/service/apiVersionSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/apiVersionSets/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/carml/1.0.1/service/apis/deploy.bicep b/carml/1.0.1/service/apis/deploy.bicep new file mode 100644 index 000000000..8fd0ee29b --- /dev/null +++ b/carml/1.0.1/service/apis/deploy.bicep @@ -0,0 +1,157 @@ +@description('Required. API revision identifier. Must be unique in the current API Management service instance. Non-current revision has ;rev=n as a suffix where n is the revision number.') +param name string + +@description('Optional. Array of Policies to apply to the Service API.') +param policies array = [] + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Describes the Revision of the API. If no value is provided, default revision 1 is created') +param apiRevision string = '' + +@description('Optional. Description of the API Revision.') +param apiRevisionDescription string = '' + +@description('Optional. Type of API to create. * http creates a SOAP to REST API * soap creates a SOAP pass-through API.') +@allowed([ + 'http' + 'soap' +]) +param apiType string = 'http' + +@description('Optional. Indicates the Version identifier of the API if the API is versioned') +param apiVersion string = '' + +@description('Optional. Indicates the Version identifier of the API version set') +param apiVersionSetId string = '' + +@description('Optional. Description of the API Version.') +param apiVersionDescription string = '' + +@description('Optional. Collection of authentication settings included into this API.') +param authenticationSettings object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Description of the API. May include HTML formatting tags.') +param apiDescription string = '' + +@description('Required. API name. Must be 1 to 300 characters long.') +@maxLength(300) +param displayName string + +@description('Optional. Format of the Content in which the API is getting imported.') +@allowed([ + 'wadl-xml' + 'wadl-link-json' + 'swagger-json' + 'swagger-link-json' + 'wsdl' + 'wsdl-link' + 'openapi' + 'openapi+json' + 'openapi-link' + 'openapi+json-link' +]) +param format string = 'openapi' + +@description('Optional. Indicates if API revision is current API revision.') +param isCurrent bool = true + +@description('Required. Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API.') +param path string + +@description('Optional. Describes on which protocols the operations in this API can be invoked. - HTTP or HTTPS') +param protocols array = [ + 'https' +] + +@description('Optional. Absolute URL of the backend service implementing this API. Cannot be more than 2000 characters long.') +@maxLength(2000) +param serviceUrl string = '' + +@description('Optional. API identifier of the source API.') +param sourceApiId string = '' + +@description('Optional. Protocols over which API is made available.') +param subscriptionKeyParameterNames object = {} + +@description('Optional. Specifies whether an API or Product subscription is required for accessing the API.') +param subscriptionRequired bool = false + +@description('Optional. Type of API.') +@allowed([ + 'http' + 'soap' +]) +param type string = 'http' + +@description('Optional. Content value when Importing an API.') +param value string = '' + +@description('Optional. Criteria to limit import of WSDL to a subset of the document.') +param wsdlSelector object = {} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource api 'Microsoft.ApiManagement/service/apis@2021-08-01' = { + name: name + parent: service + properties: { + apiRevision: !empty(apiRevision) ? apiRevision : null + apiRevisionDescription: !empty(apiRevisionDescription) ? apiRevisionDescription : null + apiType: !empty(apiType) ? apiType : null + apiVersion: !empty(apiVersion) ? apiVersion : null + apiVersionDescription: !empty(apiVersionDescription) ? apiVersionDescription : null + apiVersionSetId: !empty(apiVersionSetId) ? apiVersionSetId : null + authenticationSettings: authenticationSettings + description: apiDescription + displayName: displayName + format: !empty(value) ? format : null + isCurrent: isCurrent + path: path + protocols: protocols + serviceUrl: !empty(serviceUrl) ? serviceUrl : null + sourceApiId: !empty(sourceApiId) ? sourceApiId : null + subscriptionKeyParameterNames: !empty(subscriptionKeyParameterNames) ? subscriptionKeyParameterNames : null + subscriptionRequired: subscriptionRequired + type: type + value: !empty(value) ? value : null + wsdlSelector: wsdlSelector + } +} + +module policy 'policies/deploy.bicep' = [for (policy, index) in policies: { + name: '${deployment().name}-Policy-${index}' + params: { + apiManagementServiceName: apiManagementServiceName + apiName: api.name + format: contains(policy, 'format') ? policy.format : 'xml' + value: policy.value + } +}] + +@description('The name of the API management service API') +output name string = api.name + +@description('The resource ID of the API management service API') +output resourceId string = api.id + +@description('The resource group the API management service API was deployed to') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/apis/policies/deploy.bicep b/carml/1.0.1/service/apis/policies/deploy.bicep new file mode 100644 index 000000000..dd8161aed --- /dev/null +++ b/carml/1.0.1/service/apis/policies/deploy.bicep @@ -0,0 +1,61 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. The name of the of the API.') +param apiName string + +@description('Optional. The name of the policy') +param name string = 'policy' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Format of the policyContent.') +@allowed([ + 'rawxml' + 'rawxml-link' + 'xml' + 'xml-link' +]) +param format string = 'xml' + +@description('Required. Contents of the Policy as defined by the format.') +param value string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName + + resource api 'apis@2021-08-01' existing = { + name: apiName + } +} + +resource policy 'Microsoft.ApiManagement/service/apis/policies@2021-08-01' = { + name: name + parent: service::api + properties: { + format: format + value: value + } +} + +@description('The resource ID of the API policy') +output resourceId string = policy.id + +@description('The name of the API policy') +output name string = policy.name + +@description('The resource group the API policy was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/apis/policies/readme.md b/carml/1.0.1/service/apis/policies/readme.md new file mode 100644 index 000000000..11fee83a4 --- /dev/null +++ b/carml/1.0.1/service/apis/policies/readme.md @@ -0,0 +1,45 @@ +# API Management Service APIs Policies `[Microsoft.ApiManagement/service/apis/policies]` + +This module deploys API Management Service APIs policies. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/apis/policies` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `apiName` | string | The name of the of the API. | +| `value` | string | Contents of the Policy as defined by the format. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `format` | string | `'xml'` | `[rawxml, rawxml-link, xml, xml-link]` | Format of the policyContent. | +| `name` | string | `'policy'` | | The name of the policy | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API policy | +| `resourceGroupName` | string | The resource group the API policy was deployed into | +| `resourceId` | string | The resource ID of the API policy | + +## Template references + +- [Service/Apis/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis/policies) diff --git a/carml/1.0.1/service/apis/policies/version.json b/carml/1.0.1/service/apis/policies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/apis/policies/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/carml/1.0.1/service/apis/readme.md b/carml/1.0.1/service/apis/readme.md new file mode 100644 index 000000000..7086dc6a8 --- /dev/null +++ b/carml/1.0.1/service/apis/readme.md @@ -0,0 +1,88 @@ +# API Management Service APIs `[Microsoft.ApiManagement/service/apis]` + +This module deploys API Management Service APIs. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apis/policies` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `displayName` | string | API name. Must be 1 to 300 characters long. | +| `name` | string | API revision identifier. Must be unique in the current API Management service instance. Non-current revision has ;rev=n as a suffix where n is the revision number. | +| `path` | string | Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `apiDescription` | string | `''` | | Description of the API. May include HTML formatting tags. | +| `apiRevision` | string | `''` | | Describes the Revision of the API. If no value is provided, default revision 1 is created | +| `apiRevisionDescription` | string | `''` | | Description of the API Revision. | +| `apiType` | string | `'http'` | `[http, soap]` | Type of API to create. * http creates a SOAP to REST API * soap creates a SOAP pass-through API. | +| `apiVersion` | string | `''` | | Indicates the Version identifier of the API if the API is versioned | +| `apiVersionDescription` | string | `''` | | Description of the API Version. | +| `apiVersionSetId` | string | `''` | | Indicates the Version identifier of the API version set | +| `authenticationSettings` | object | `{object}` | | Collection of authentication settings included into this API. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `format` | string | `'openapi'` | `[wadl-xml, wadl-link-json, swagger-json, swagger-link-json, wsdl, wsdl-link, openapi, openapi+json, openapi-link, openapi+json-link]` | Format of the Content in which the API is getting imported. | +| `isCurrent` | bool | `True` | | Indicates if API revision is current API revision. | +| `policies` | _[policies](policies/readme.md)_ array | `[]` | | Array of Policies to apply to the Service API. | +| `protocols` | array | `[https]` | | Describes on which protocols the operations in this API can be invoked. - HTTP or HTTPS | +| `serviceUrl` | string | `''` | | Absolute URL of the backend service implementing this API. Cannot be more than 2000 characters long. | +| `sourceApiId` | string | `''` | | API identifier of the source API. | +| `subscriptionKeyParameterNames` | object | `{object}` | | Protocols over which API is made available. | +| `subscriptionRequired` | bool | `False` | | Specifies whether an API or Product subscription is required for accessing the API. | +| `type` | string | `'http'` | `[http, soap]` | Type of API. | +| `value` | string | `''` | | Content value when Importing an API. | +| `wsdlSelector` | object | `{object}` | | Criteria to limit import of WSDL to a subset of the document. | + + +### Parameter Usage: `apiVersionSet` + +```json +"apiVersionSet":{ + "value":{ + "name":"", //Required. API Version Set identifier. Must be unique in the current API Management service instance. + "properties":{ + "description": "string", //Description of API Version Set. + "versionQueryName": "string", //Optional. Name of query parameter that indicates the API Version if versioningScheme is set to query. + "versionHeaderName": "string", //Optional. Name of HTTP header parameter that indicates the API Version if versioningScheme is set to header. + "displayName": "string", //Required. Name of API Version Set + "versioningScheme": "string" //Required. An value that determines where the API Version identifer will be located in a HTTP request. - Segment, Query, Header + } + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service API | +| `resourceGroupName` | string | The resource group the API management service API was deployed to | +| `resourceId` | string | The resource ID of the API management service API | + +## Template references + +- [Service/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis) +- [Service/Apis/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis/policies) diff --git a/carml/1.0.1/service/apis/version.json b/carml/1.0.1/service/apis/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/apis/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/carml/1.0.1/service/authorizationServers/deploy.bicep b/carml/1.0.1/service/authorizationServers/deploy.bicep new file mode 100644 index 000000000..fb6d247c3 --- /dev/null +++ b/carml/1.0.1/service/authorizationServers/deploy.bicep @@ -0,0 +1,114 @@ +@description('Required. Identifier of the authorization server.') +param name string + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. OAuth authorization endpoint. See .') +param authorizationEndpoint string + +@description('Optional. HTTP verbs supported by the authorization endpoint. GET must be always present. POST is optional. - HEAD, OPTIONS, TRACE, GET, POST, PUT, PATCH, DELETE') +param authorizationMethods array = [ + 'GET' +] + +@description('Optional. Specifies the mechanism by which access token is passed to the API. - authorizationHeader or query') +param bearerTokenSendingMethods array = [ + 'authorizationHeader' +] + +@description('Optional. Method of authentication supported by the token endpoint of this authorization server. Possible values are Basic and/or Body. When Body is specified, client credentials and other parameters are passed within the request body in the application/x-www-form-urlencoded format. - Basic or Body') +param clientAuthenticationMethod array = [ + 'Basic' +] + +@description('Required. Client or app ID registered with this authorization server.') +@secure() +param clientId string + +@description('Optional. Optional reference to a page where client or app registration for this authorization server is performed. Contains absolute URL to entity being referenced.') +param clientRegistrationEndpoint string = '' + +@description('Required. Client or app secret registered with this authorization server. This property will not be filled on \'GET\' operations! Use \'/listSecrets\' POST request to get the value.') +@secure() +param clientSecret string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Access token scope that is going to be requested by default. Can be overridden at the API level. Should be provided in the form of a string containing space-delimited values.') +param defaultScope string = '' + +@description('Optional. Description of the authorization server. Can contain HTML formatting tags.') +param serverDescription string = '' + +@description('Required. Form of an authorization grant, which the client uses to request the access token. - authorizationCode, implicit, resourceOwnerPassword, clientCredentials') +param grantTypes array + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner password.') +param resourceOwnerPassword string = '' + +@description('Optional. Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner username.') +param resourceOwnerUsername string = '' + +@description('Optional. If true, authorization server will include state parameter from the authorization request to its response. Client may use state parameter to raise protocol security.') +param supportState bool = false + +@description('Optional. Additional parameters required by the token endpoint of this authorization server represented as an array of JSON objects with name and value string properties, i.e. {"name" : "name value", "value": "a value"}. - TokenBodyParameterContract object') +param tokenBodyParameters array = [] + +@description('Optional. OAuth token endpoint. Contains absolute URI to entity being referenced.') +param tokenEndpoint string = '' + +var defaultAuthorizationMethods = [ + 'GET' +] +var setAuthorizationMethods = union(authorizationMethods, defaultAuthorizationMethods) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource authorizationServer 'Microsoft.ApiManagement/service/authorizationServers@2021-08-01' = { + name: name + parent: service + properties: { + description: serverDescription + authorizationMethods: setAuthorizationMethods + clientAuthenticationMethod: clientAuthenticationMethod + tokenBodyParameters: tokenBodyParameters + tokenEndpoint: tokenEndpoint + supportState: supportState + defaultScope: defaultScope + bearerTokenSendingMethods: bearerTokenSendingMethods + resourceOwnerUsername: resourceOwnerUsername + resourceOwnerPassword: resourceOwnerPassword + displayName: name + clientRegistrationEndpoint: clientRegistrationEndpoint + authorizationEndpoint: authorizationEndpoint + grantTypes: grantTypes + clientId: clientId + clientSecret: clientSecret + } +} + +@description('The name of the API management service authorization server') +output name string = authorizationServer.name + +@description('The resource ID of the API management service authorization server') +output resourceId string = authorizationServer.id + +@description('The resource group the API management service authorization server was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/authorizationServers/readme.md b/carml/1.0.1/service/authorizationServers/readme.md new file mode 100644 index 000000000..a603f8e1c --- /dev/null +++ b/carml/1.0.1/service/authorizationServers/readme.md @@ -0,0 +1,63 @@ +# API Management Service Authorization Servers `[Microsoft.ApiManagement/service/authorizationServers]` + +This module deploys API Management Service Authorization Servers. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/authorizationServers` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `authorizationEndpoint` | string | OAuth authorization endpoint. See . | +| `clientId` | secureString | Client or app ID registered with this authorization server. | +| `clientSecret` | secureString | Client or app secret registered with this authorization server. This property will not be filled on 'GET' operations! Use '/listSecrets' POST request to get the value. | +| `grantTypes` | array | Form of an authorization grant, which the client uses to request the access token. - authorizationCode, implicit, resourceOwnerPassword, clientCredentials | +| `name` | string | Identifier of the authorization server. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `authorizationMethods` | array | `[GET]` | HTTP verbs supported by the authorization endpoint. GET must be always present. POST is optional. - HEAD, OPTIONS, TRACE, GET, POST, PUT, PATCH, DELETE | +| `bearerTokenSendingMethods` | array | `[authorizationHeader]` | Specifies the mechanism by which access token is passed to the API. - authorizationHeader or query | +| `clientAuthenticationMethod` | array | `[Basic]` | Method of authentication supported by the token endpoint of this authorization server. Possible values are Basic and/or Body. When Body is specified, client credentials and other parameters are passed within the request body in the application/x-www-form-urlencoded format. - Basic or Body | +| `clientRegistrationEndpoint` | string | `''` | Optional reference to a page where client or app registration for this authorization server is performed. Contains absolute URL to entity being referenced. | +| `defaultScope` | string | `''` | Access token scope that is going to be requested by default. Can be overridden at the API level. Should be provided in the form of a string containing space-delimited values. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `resourceOwnerPassword` | string | `''` | Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner password. | +| `resourceOwnerUsername` | string | `''` | Can be optionally specified when resource owner password grant type is supported by this authorization server. Default resource owner username. | +| `serverDescription` | string | `''` | Description of the authorization server. Can contain HTML formatting tags. | +| `supportState` | bool | `False` | If true, authorization server will include state parameter from the authorization request to its response. Client may use state parameter to raise protocol security. | +| `tokenBodyParameters` | array | `[]` | Additional parameters required by the token endpoint of this authorization server represented as an array of JSON objects with name and value string properties, i.e. {"name" : "name value", "value": "a value"}. - TokenBodyParameterContract object | +| `tokenEndpoint` | string | `''` | OAuth token endpoint. Contains absolute URI to entity being referenced. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service authorization server | +| `resourceGroupName` | string | The resource group the API management service authorization server was deployed into | +| `resourceId` | string | The resource ID of the API management service authorization server | + +## Template references + +- [Service/Authorizationservers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/authorizationServers) diff --git a/carml/1.0.1/service/authorizationServers/version.json b/carml/1.0.1/service/authorizationServers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/authorizationServers/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/carml/1.0.1/service/backends/deploy.bicep b/carml/1.0.1/service/backends/deploy.bicep new file mode 100644 index 000000000..0a4884aa3 --- /dev/null +++ b/carml/1.0.1/service/backends/deploy.bicep @@ -0,0 +1,81 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. Backend Name.') +param name string + +@description('Optional. Backend Credentials Contract Properties.') +param credentials object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Backend Description.') +param backendDescription string = '' + +@description('Optional. Backend communication protocol. - http or soap') +param protocol string = 'http' + +@description('Optional. Backend Proxy Contract Properties') +param proxy object = {} + +@description('Optional. Management Uri of the Resource in External System. This URL can be the Arm Resource ID of Logic Apps, Function Apps or API Apps.') +param resourceId string = '' + +@description('Optional. Backend Service Fabric Cluster Properties.') +param serviceFabricCluster object = {} + +@description('Optional. Backend Title.') +param title string = '' + +@description('Optional. Backend TLS Properties') +param tls object = { + validateCertificateChain: false + validateCertificateName: false +} + +@description('Required. Runtime URL of the Backend.') +param url string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource backend 'Microsoft.ApiManagement/service/backends@2021-08-01' = { + name: name + parent: service + properties: { + title: !empty(title) ? title : null + description: !empty(backendDescription) ? backendDescription : null + resourceId: !empty(resourceId) ? resourceId : null + properties: { + serviceFabricCluster: !empty(serviceFabricCluster) ? serviceFabricCluster : null + } + credentials: !empty(credentials) ? credentials : null + proxy: !empty(proxy) ? proxy : null + tls: !empty(tls) ? tls : null + url: url + protocol: protocol + } +} + +@description('The resource ID of the API management service backend') +output resourceId string = backend.id + +@description('The name of the API management service backend') +output name string = backend.name + +@description('The resource group the API management service backend was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/backends/readme.md b/carml/1.0.1/service/backends/readme.md new file mode 100644 index 000000000..c42bcc1cc --- /dev/null +++ b/carml/1.0.1/service/backends/readme.md @@ -0,0 +1,144 @@ +# API Management Service Backends `[Microsoft.ApiManagement/service/backends]` + +This module deploys API Management Service Backends. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/backends` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `name` | string | Backend Name. | +| `url` | string | Runtime URL of the Backend. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `backendDescription` | string | `''` | Backend Description. | +| `credentials` | object | `{object}` | Backend Credentials Contract Properties. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `protocol` | string | `'http'` | Backend communication protocol. - http or soap | +| `proxy` | object | `{object}` | Backend Proxy Contract Properties | +| `resourceId` | string | `''` | Management Uri of the Resource in External System. This URL can be the Arm Resource ID of Logic Apps, Function Apps or API Apps. | +| `serviceFabricCluster` | object | `{object}` | Backend Service Fabric Cluster Properties. | +| `title` | string | `''` | Backend Title. | +| `tls` | object | `{object}` | Backend TLS Properties | + + +### Parameters - credentials + +| Parameter Name| Type | Default Value | Possible values | Description | +| :-- | :-- | :--- | :-- | :- | +| `certificate` | array | | | Optional. List of Client Certificate Thumbprint. - string | +| `query` | object | | | Optional. Query Parameter description. | +| `header` | object | | | Optional. Header Parameter description. | +| `authorization` | object | | | Optional. Authorization header authentication | + +### Parameter Usage: `credentials` + +```json +"credentials": { + "value":{ + "certificate": [ + "string" + ], + "query": {}, + "header": {}, + "authorization": { + "scheme": "Authentication Scheme name.-string", + "parameter": "Authentication Parameter value. - string" + } + } +} +``` + +### Parameter Usage: `proxy` + +| Parameter Name | Type | Default Value | Possible values | Description | +| :- | :- | :- | :- | :- | +| `url` | string | | | WebProxy Server AbsoluteUri property which includes the entire URI stored in the URI instance, including all fragments and query strings.| +| `username` | string | | | Username to connect to the WebProxy server| +| `password`| string | | | Password to connect to the WebProxy Server| + +```json +"proxy": { + "value":{ + "url": "string", + "username": "string", + "password": "string" + } +} +``` + +### Parameter Usage: `serviceFabricCluster` + +| Parameter Name | Type | Default Value | Possible values | Description | +| :-- | :-- | :--- | :-- | :- | +| `clientCertificatethumbprint` | string | | | Required (if this object is used).The client certificate thumbprint for the management endpoint.| +| `maxPartitionResolutionRetries` | integer | | | Optional. Maximum number of retries while attempting resolve the partition. | +| `managementEndpoints` | array | | | Required (if this object is used). The cluster management endpoint. - string| +| `serverCertificateThumbprints`| array | | | Optional. Thumbprints of certificates cluster management service uses for TLS communication - string| +| `serverX509Names` | array | | | Optional. Server X509 Certificate Names Collection| + +```json +"serviceFabricCluster": { + "value":{ + "clientCertificatethumbprint": "string", + "maxPartitionResolutionRetries": "integer", + "managementEndpoints": [ + "string" + ], + "serverCertificateThumbprints": [ + "string" + ], + "serverX509Names": [ + { + "name": "Common Name of the Certificate.- string", + "issuerCertificateThumbprint": "Thumbprint for the Issuer of the Certificate. - string" + } + ] + } +} +``` + +### Parameter Usage: `tls` + +```json +"tls": { + "value":{ + "validateCertificateChain": "Flag indicating whether SSL certificate chain validation should be done when using self-signed certificates for this backend host. - boolean", + "validateCertificateName": "Flag indicating whether SSL certificate name validation should be done when using self-signed certificates for this backend host. - boolean" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service backend | +| `resourceGroupName` | string | The resource group the API management service backend was deployed into | +| `resourceId` | string | The resource ID of the API management service backend | + +## Template references + +- [Service/Backends](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/backends) diff --git a/carml/1.0.1/service/backends/version.json b/carml/1.0.1/service/backends/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/backends/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/carml/1.0.1/service/caches/deploy.bicep b/carml/1.0.1/service/caches/deploy.bicep new file mode 100644 index 000000000..e0ae35cbd --- /dev/null +++ b/carml/1.0.1/service/caches/deploy.bicep @@ -0,0 +1,56 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. Identifier of the Cache entity. Cache identifier (should be either \'default\' or valid Azure region identifier).') +param name string + +@description('Required. Runtime connection string to cache. Can be referenced by a named value like so, {{}}') +param connectionString string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Cache description') +param cacheDescription string = '' + +@description('Optional. Original uri of entity in external system cache points to.') +param resourceId string = '' + +@description('Required. Location identifier to use cache from (should be either \'default\' or valid Azure region identifier)') +param useFromLocation string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource cache 'Microsoft.ApiManagement/service/caches@2021-08-01' = { + name: name + parent: service + properties: { + description: !empty(cacheDescription) ? cacheDescription : null + connectionString: connectionString + useFromLocation: useFromLocation + resourceId: !empty(resourceId) ? resourceId : null + } +} + +@description('The resource ID of the API management service cache') +output resourceId string = cache.id + +@description('The name of the API management service cache') +output name string = cache.name + +@description('The resource group the API management service cache was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/caches/readme.md b/carml/1.0.1/service/caches/readme.md new file mode 100644 index 000000000..054367568 --- /dev/null +++ b/carml/1.0.1/service/caches/readme.md @@ -0,0 +1,52 @@ +# API Management Service Cache `[Microsoft.ApiManagement/service/caches]` + +This module deploys an API Management Service Cache. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/caches` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `connectionString` | string | Runtime connection string to cache. Can be referenced by a named value like so, {{}} | +| `name` | string | Identifier of the Cache entity. Cache identifier (should be either 'default' or valid Azure region identifier). | +| `useFromLocation` | string | Location identifier to use cache from (should be either 'default' or valid Azure region identifier) | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `cacheDescription` | string | `''` | Cache description | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `resourceId` | string | `''` | Original uri of entity in external system cache points to. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service cache | +| `resourceGroupName` | string | The resource group the API management service cache was deployed into | +| `resourceId` | string | The resource ID of the API management service cache | + +## Template references + +- [Service/Caches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/caches) diff --git a/carml/1.0.1/service/caches/version.json b/carml/1.0.1/service/caches/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/caches/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/carml/1.0.1/service/deploy.bicep b/carml/1.0.1/service/deploy.bicep new file mode 100644 index 000000000..64a264454 --- /dev/null +++ b/carml/1.0.1/service/deploy.bicep @@ -0,0 +1,452 @@ +@description('Optional. Additional datacenter locations of the API Management service.') +param additionalLocations array = [] + +@description('Required. The name of the of the API Management service.') +param name string + +@description('Optional. List of Certificates that need to be installed in the API Management service. Max supported certificates that can be installed is 10.') +@maxLength(10) +param certificates array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Custom properties of the API Management service.') +param customProperties object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Property only valid for an API Management service deployed in multiple locations. This can be used to disable the gateway in master region.') +param disableGateway bool = false + +@description('Optional. Property only meant to be used for Consumption SKU Service. This enforces a client certificate to be presented on each request to the gateway. This also enables the ability to authenticate the certificate in the policy on the gateway.') +param enableClientCertificate bool = false + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Custom hostname configuration of the API Management service.') +param hostnameConfigurations array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Limit control plane API calls to API Management service with version equal to or newer than this value.') +param minApiVersion string = '' + +@description('Optional. The notification sender email address for the service.') +param notificationSenderEmail string = 'apimgmt-noreply@mail.windowsazure.com' + +@description('Required. The email address of the owner of the service.') +param publisherEmail string + +@description('Required. The name of the owner of the service.') +param publisherName string + +@description('Optional. Undelete API Management Service if it was previously soft-deleted. If this flag is specified and set to True all other properties will be ignored.') +param restore bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The pricing tier of this API Management service.') +@allowed([ + 'Consumption' + 'Developer' + 'Basic' + 'Standard' + 'Premium' +]) +param sku string = 'Developer' + +@description('Optional. The instance size of this API Management service.') +@allowed([ + 1 + 2 +]) +param skuCount int = 1 + +@description('Optional. The full resource ID of a subnet in a virtual network to deploy the API Management service in.') +param subnetResourceId string = '' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The type of VPN in which API Management service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only.') +@allowed([ + 'None' + 'External' + 'Internal' +]) +param virtualNetworkType string = 'None' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. A list of availability zones denoting where the resource needs to come from.') +param zones array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'GatewayLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'GatewayLogs' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] +@description('Optional. Necessary to create a new GUID.') +param newGuidValue string = newGuid() + +@description('Optional. APIs.') +param apis array = [] +@description('Optional. API Version Sets.') +param apiVersionSets array = [] +@description('Optional. Authorization servers.') +param authorizationServers array = [] +@description('Optional. Backends.') +param backends array = [] +@description('Optional. Caches.') +param caches array = [] +@description('Optional. Identity providers.') +param identityProviders array = [] +@description('Optional. Named values.') +param namedValues array = [] +@description('Optional. Policies.') +param policies array = [] +@description('Optional. Portal settings.') +param portalSettings array = [] +@description('Optional. Products.') +param products array = [] +@description('Optional. Subscriptions.') +param subscriptions array = [] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource apiManagementService 'Microsoft.ApiManagement/service@2021-08-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + capacity: skuCount + } + zones: zones + identity: identity + properties: { + publisherEmail: publisherEmail + publisherName: publisherName + notificationSenderEmail: notificationSenderEmail + hostnameConfigurations: hostnameConfigurations + additionalLocations: additionalLocations + customProperties: customProperties + certificates: certificates + enableClientCertificate: enableClientCertificate ? true : null + disableGateway: disableGateway + virtualNetworkType: virtualNetworkType + virtualNetworkConfiguration: !empty(subnetResourceId) ? json('{"subnetResourceId": "${subnetResourceId}"}') : null + apiVersionConstraint: !empty(minApiVersion) ? json('{"minApiVersion": "${minApiVersion}"}') : null + restore: restore + } +} + +module apis_resource 'apis/deploy.bicep' = [for (api, index) in apis: { + name: '${uniqueString(deployment().name, location)}-Apim-Api-${index}' + params: { + apiManagementServiceName: apiManagementService.name + displayName: api.displayName + name: api.name + path: api.path + apiDescription: contains(api, 'apiDescription') ? api.apiDescription : '' + apiRevision: contains(api, 'apiRevision') ? api.apiRevision : '' + apiRevisionDescription: contains(api, 'apiRevisionDescription') ? api.apiRevisionDescription : '' + apiType: contains(api, 'apiType') ? api.apiType : 'http' + apiVersion: contains(api, 'apiVersion') ? api.apiVersion : '' + apiVersionDescription: contains(api, 'apiVersionDescription') ? api.apiVersionDescription : '' + apiVersionSetId: contains(api, 'apiVersionSetId') ? api.apiVersionSetId : '' + authenticationSettings: contains(api, 'authenticationSettings') ? api.authenticationSettings : {} + format: contains(api, 'format') ? api.format : 'openapi' + isCurrent: contains(api, 'isCurrent') ? api.isCurrent : true + protocols: contains(api, 'protocols') ? api.protocols : [ + 'https' + ] + policies: contains(api, 'policies') ? api.policies : [] + serviceUrl: contains(api, 'serviceUrl') ? api.serviceUrl : '' + sourceApiId: contains(api, 'sourceApiId') ? api.sourceApiId : '' + subscriptionKeyParameterNames: contains(api, 'subscriptionKeyParameterNames') ? api.subscriptionKeyParameterNames : {} + subscriptionRequired: contains(api, 'subscriptionRequired') ? api.subscriptionRequired : false + type: contains(api, 'type') ? api.type : 'http' + value: contains(api, 'value') ? api.value : '' + wsdlSelector: contains(api, 'wsdlSelector') ? api.wsdlSelector : {} + } + dependsOn: [ + apiVersionSet_resource + ] +}] + +module apiVersionSet_resource 'apiVersionSets/deploy.bicep' = [for (apiVersionSet, index) in apiVersionSets: { + name: '${uniqueString(deployment().name, location)}-Apim-ApiVersionSet-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: apiVersionSet.name + properties: contains(apiVersionSet, 'properties') ? apiVersionSet.properties : {} + } +}] + +module authorizationServers_resource '.bicep/nested_authorizationServers.bicep' = [for (authorizationServer, index) in authorizationServers: { + name: '${uniqueString(deployment().name, location)}-Apim-AuthorizationServer-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: authorizationServer.name + authorizationEndpoint: authorizationServer.authorizationEndpoint + authorizationMethods: contains(authorizationServer, 'authorizationMethods') ? authorizationServer.authorizationMethods : [ + 'GET' + ] + bearerTokenSendingMethods: contains(authorizationServer, 'bearerTokenSendingMethods') ? authorizationServer.bearerTokenSendingMethods : [ + 'authorizationHeader' + ] + clientAuthenticationMethod: contains(authorizationServer, 'clientAuthenticationMethod') ? authorizationServer.clientAuthenticationMethod : [ + 'Basic' + ] + clientCredentialsKeyVaultId: authorizationServer.clientCredentialsKeyVaultId + clientIdSecretName: authorizationServer.clientIdSecretName + clientSecretSecretName: authorizationServer.clientSecretSecretName + clientRegistrationEndpoint: contains(authorizationServer, 'clientRegistrationEndpoint') ? authorizationServer.clientRegistrationEndpoint : '' + defaultScope: contains(authorizationServer, 'defaultScope') ? authorizationServer.defaultScope : '' + grantTypes: authorizationServer.grantTypes + resourceOwnerPassword: contains(authorizationServer, 'resourceOwnerPassword') ? authorizationServer.resourceOwnerPassword : '' + resourceOwnerUsername: contains(authorizationServer, 'resourceOwnerUsername') ? authorizationServer.resourceOwnerUsername : '' + serverDescription: contains(authorizationServer, 'serverDescription') ? authorizationServer.serverDescription : '' + supportState: contains(authorizationServer, 'supportState') ? authorizationServer.supportState : false + tokenBodyParameters: contains(authorizationServer, 'tokenBodyParameters') ? authorizationServer.tokenBodyParameters : [] + tokenEndpoint: contains(authorizationServer, 'tokenEndpoint') ? authorizationServer.tokenEndpoint : '' + } +}] + +module backends_resource 'backends/deploy.bicep' = [for (backend, index) in backends: { + name: '${uniqueString(deployment().name, location)}-Apim-Backend-${index}' + params: { + apiManagementServiceName: apiManagementService.name + url: contains(backend, 'url') ? backend.url : '' + backendDescription: contains(backend, 'backendDescription') ? backend.backendDescription : '' + credentials: contains(backend, 'credentials') ? backend.credentials : {} + name: backend.name + protocol: contains(backend, 'protocol') ? backend.protocol : 'http' + proxy: contains(backend, 'proxy') ? backend.proxy : {} + resourceId: contains(backend, 'resourceId') ? backend.resourceId : '' + serviceFabricCluster: contains(backend, 'serviceFabricCluster') ? backend.serviceFabricCluster : {} + title: contains(backend, 'title') ? backend.title : '' + tls: contains(backend, 'tls') ? backend.tls : { + validateCertificateChain: false + validateCertificateName: false + } + } +}] + +module caches_resource 'caches/deploy.bicep' = [for (cache, index) in caches: { + name: '${uniqueString(deployment().name, location)}-Apim-Cache-${index}' + params: { + apiManagementServiceName: apiManagementService.name + cacheDescription: contains(cache, 'cacheDescription') ? cache.cacheDescription : '' + connectionString: cache.connectionString + name: cache.name + resourceId: contains(cache, 'resourceId') ? cache.resourceId : '' + useFromLocation: cache.useFromLocation + } +}] + +module identityProvider_resource 'identityProviders/deploy.bicep' = [for (identityProvider, index) in identityProviders: { + name: '${uniqueString(deployment().name, location)}-Apim-IdentityProvider-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: identityProvider.name + enableIdentityProviders: contains(identityProvider, 'enableIdentityProviders') ? identityProvider.enableIdentityProviders : false + identityProviderAllowedTenants: contains(identityProvider, 'identityProviderAllowedTenants') ? identityProvider.identityProviderAllowedTenants : [] + identityProviderAuthority: contains(identityProvider, 'identityProviderAuthority') ? identityProvider.identityProviderAuthority : '' + identityProviderClientId: contains(identityProvider, 'identityProviderClientId') ? identityProvider.identityProviderClientId : '' + identityProviderClientSecret: contains(identityProvider, 'identityProviderClientSecret') ? identityProvider.identityProviderClientSecret : '' + identityProviderPasswordResetPolicyName: contains(identityProvider, 'identityProviderPasswordResetPolicyName') ? identityProvider.identityProviderPasswordResetPolicyName : '' + identityProviderProfileEditingPolicyName: contains(identityProvider, 'identityProviderProfileEditingPolicyName') ? identityProvider.identityProviderProfileEditingPolicyName : '' + identityProviderSignInPolicyName: contains(identityProvider, 'identityProviderSignInPolicyName') ? identityProvider.identityProviderSignInPolicyName : '' + identityProviderSignInTenant: contains(identityProvider, 'identityProviderSignInTenant') ? identityProvider.identityProviderSignInTenant : '' + identityProviderSignUpPolicyName: contains(identityProvider, 'identityProviderSignUpPolicyName') ? identityProvider.identityProviderSignUpPolicyName : '' + identityProviderType: contains(identityProvider, 'identityProviderType') ? identityProvider.identityProviderType : 'aad' + } +}] + +module namedValues_resource 'namedValues/deploy.bicep' = [for (namedValue, index) in namedValues: { + name: '${uniqueString(deployment().name, location)}-Apim-NamedValue-${index}' + params: { + apiManagementServiceName: apiManagementService.name + displayName: namedValue.displayName + keyVault: contains(namedValue, 'keyVault') ? namedValue.keyVault : {} + name: namedValue.name + namedValueTags: contains(namedValue, 'namedValueTags') ? namedValue.namedValueTags : [] + secret: contains(namedValue, 'secret') ? namedValue.secret : false + value: contains(namedValue, 'value') ? namedValue.value : newGuidValue + } +}] + +module portalSettings_resource 'portalsettings/deploy.bicep' = [for (portalSetting, index) in portalSettings: { + name: '${uniqueString(deployment().name, location)}-Apim-PortalSetting-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: portalSetting.name + properties: contains(portalSetting, 'properties') ? portalSetting.properties : {} + } +}] + +module policy_resource 'policies/deploy.bicep' = [for (policy, index) in policies: { + name: '${uniqueString(deployment().name, location)}-Apim-Policy-${index}' + params: { + apiManagementServiceName: apiManagementService.name + value: policy.value + format: contains(policy, 'format') ? policy.format : 'xml' + } +}] + +module products_resource 'products/deploy.bicep' = [for (product, index) in products: { + name: '${uniqueString(deployment().name, location)}-Apim-Product-${index}' + params: { + apiManagementServiceName: apiManagementService.name + apis: contains(product, 'apis') ? product.apis : [] + approvalRequired: contains(product, 'approvalRequired') ? product.approvalRequired : false + groups: contains(product, 'groups') ? product.groups : [] + name: product.name + productDescription: contains(product, 'productDescription') ? product.productDescription : '' + state: contains(product, 'state') ? product.state : 'published' + subscriptionRequired: contains(product, 'subscriptionRequired') ? product.subscriptionRequired : false + subscriptionsLimit: contains(product, 'subscriptionsLimit') ? product.subscriptionsLimit : 1 + terms: contains(product, 'terms') ? product.terms : '' + } + dependsOn: [ + apis_resource + ] +}] + +module subscriptions_resource 'subscriptions/deploy.bicep' = [for (subscription, index) in subscriptions: { + name: '${uniqueString(deployment().name, location)}-Apim-Subscription-${index}' + params: { + apiManagementServiceName: apiManagementService.name + name: contains(subscription, 'name') ? subscription.name : '' + allowTracing: contains(subscription, 'allowTracing') ? subscription.allowTracing : false + ownerId: contains(subscription, 'ownerId') ? subscription.ownerId : '' + primaryKey: contains(subscription, 'primaryKey') ? subscription.primaryKey : '' + scope: contains(subscription, 'scope') ? subscription.scope : '/apis' + secondaryKey: contains(subscription, 'secondaryKey') ? subscription.secondaryKey : '' + state: contains(subscription, 'state') ? subscription.state : '' + } +}] + +resource apiManagementService_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${apiManagementService.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: apiManagementService +} + +resource apiManagementService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: apiManagementService +} + +module apiManagementService_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Apim-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: apiManagementService.id + } +}] + +@description('The name of the API management service') +output name string = apiManagementService.name + +@description('The resource ID of the API management service') +output resourceId string = apiManagementService.id + +@description('The resource group the API management service was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(apiManagementService.identity, 'principalId') ? apiManagementService.identity.principalId : '' diff --git a/carml/1.0.1/service/identityProviders/deploy.bicep b/carml/1.0.1/service/identityProviders/deploy.bicep new file mode 100644 index 000000000..ea5b58d04 --- /dev/null +++ b/carml/1.0.1/service/identityProviders/deploy.bicep @@ -0,0 +1,94 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Used to enable the deployment of the identityProviders child resource.') +param enableIdentityProviders bool = false + +@description('Optional. List of Allowed Tenants when configuring Azure Active Directory login. - string') +param identityProviderAllowedTenants array = [] + +@description('Optional. OpenID Connect discovery endpoint hostname for AAD or AAD B2C.') +param identityProviderAuthority string = '' + +@description('Optional. Client ID of the Application in the external Identity Provider. Required if identity provider is used.') +param identityProviderClientId string = '' + +@description('Optional. Client secret of the Application in external Identity Provider, used to authenticate login request. Required if identity provider is used.') +@secure() +param identityProviderClientSecret string = '' + +@description('Optional. Password Reset Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderPasswordResetPolicyName string = '' + +@description('Optional. Profile Editing Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderProfileEditingPolicyName string = '' + +@description('Optional. Signin Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderSignInPolicyName string = '' + +@description('Optional. The TenantId to use instead of Common when logging into Active Directory') +param identityProviderSignInTenant string = '' + +@description('Optional. Signup Policy Name. Only applies to AAD B2C Identity Provider.') +param identityProviderSignUpPolicyName string = '' + +@description('Optional. Identity Provider Type identifier.') +@allowed([ + 'aad' + 'aadB2C' + 'facebook' + 'google' + 'microsoft' + 'twitter' +]) +param identityProviderType string = 'aad' + +@description('Required. Identity provider name') +param name string + +var isAadB2C = (identityProviderType == 'aadB2C') + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource identityProvider 'Microsoft.ApiManagement/service/identityProviders@2021-08-01' = if (enableIdentityProviders) { + name: name + parent: service + properties: { + type: identityProviderType + signinTenant: identityProviderSignInTenant + allowedTenants: identityProviderAllowedTenants + authority: identityProviderAuthority + signupPolicyName: isAadB2C ? identityProviderSignUpPolicyName : null + signinPolicyName: isAadB2C ? identityProviderSignInPolicyName : null + profileEditingPolicyName: isAadB2C ? identityProviderProfileEditingPolicyName : null + passwordResetPolicyName: isAadB2C ? identityProviderPasswordResetPolicyName : null + clientId: identityProviderClientId + clientSecret: identityProviderClientSecret + } +} + +@description('The resource ID of the API management service identity provider') +output resourceId string = identityProvider.id + +@description('The name of the API management service identity provider') +output name string = identityProvider.name + +@description('The resource group the API management service identity provider was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/identityProviders/readme.md b/carml/1.0.1/service/identityProviders/readme.md new file mode 100644 index 000000000..465cc2730 --- /dev/null +++ b/carml/1.0.1/service/identityProviders/readme.md @@ -0,0 +1,53 @@ +# API Management Service Identity Providers `[Microsoft.ApiManagement/service/identityProviders]` + +This module deploys API Management Service Identity Provider. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/identityProviders` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `name` | string | Identity provider name | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableIdentityProviders` | bool | `False` | | Used to enable the deployment of the identityProviders child resource. | +| `identityProviderAllowedTenants` | array | `[]` | | List of Allowed Tenants when configuring Azure Active Directory login. - string | +| `identityProviderAuthority` | string | `''` | | OpenID Connect discovery endpoint hostname for AAD or AAD B2C. | +| `identityProviderClientId` | string | `''` | | Client ID of the Application in the external Identity Provider. Required if identity provider is used. | +| `identityProviderClientSecret` | secureString | `''` | | Client secret of the Application in external Identity Provider, used to authenticate login request. Required if identity provider is used. | +| `identityProviderPasswordResetPolicyName` | string | `''` | | Password Reset Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderProfileEditingPolicyName` | string | `''` | | Profile Editing Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderSignInPolicyName` | string | `''` | | Signin Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderSignInTenant` | string | `''` | | The TenantId to use instead of Common when logging into Active Directory | +| `identityProviderSignUpPolicyName` | string | `''` | | Signup Policy Name. Only applies to AAD B2C Identity Provider. | +| `identityProviderType` | string | `'aad'` | `[aad, aadB2C, facebook, google, microsoft, twitter]` | Identity Provider Type identifier. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service identity provider | +| `resourceGroupName` | string | The resource group the API management service identity provider was deployed into | +| `resourceId` | string | The resource ID of the API management service identity provider | + +## Template references + +- [Service/Identityproviders](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/identityProviders) diff --git a/carml/1.0.1/service/identityProviders/version.json b/carml/1.0.1/service/identityProviders/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/identityProviders/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/carml/1.0.1/service/namedValues/deploy.bicep b/carml/1.0.1/service/namedValues/deploy.bicep new file mode 100644 index 000000000..831aba17d --- /dev/null +++ b/carml/1.0.1/service/namedValues/deploy.bicep @@ -0,0 +1,62 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. Unique name of NamedValue. It may contain only letters, digits, period, dash, and underscore characters.') +param displayName string + +@description('Optional. KeyVault location details of the namedValue. ') +param keyVault object = {} + +@description('Required. Named value Name.') +param name string + +@description('Optional. Tags that when provided can be used to filter the NamedValue list. - string') +param namedValueTags array = [] + +@description('Optional. Determines whether the value is a secret and should be encrypted or not. Default value is false.') +param secret bool = false + +@description('Optional. Value of the NamedValue. Can contain policy expressions. It may not be empty or consist only of whitespace. This property will not be filled on \'GET\' operations! Use \'/listSecrets\' POST request to get the value.') +param value string = newGuid() + +var keyVaultEmpty = empty(keyVault) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource namedValue 'Microsoft.ApiManagement/service/namedValues@2021-08-01' = { + name: name + parent: service + properties: { + tags: !empty(namedValueTags) ? namedValueTags : null + secret: secret + displayName: displayName + value: keyVaultEmpty ? value : null + keyVault: !keyVaultEmpty ? keyVault : null + } +} + +@description('The resource ID of the named value') +output resourceId string = namedValue.id + +@description('The name of the named value') +output name string = namedValue.name + +@description('The resource group the named value was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/namedValues/readme.md b/carml/1.0.1/service/namedValues/readme.md new file mode 100644 index 000000000..3dec11e8e --- /dev/null +++ b/carml/1.0.1/service/namedValues/readme.md @@ -0,0 +1,64 @@ +# API Management Service Named Values `[Microsoft.ApiManagement/service/namedValues]` + +This module deploys API Management Service Named Values. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/namedValues` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | `''` | The name of the of the API Management service. | +| `displayName` | string | | Unique name of NamedValue. It may contain only letters, digits, period, dash, and underscore characters. | +| `name` | string | | Named value Name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `keyVault` | object | `{object}` | KeyVault location details of the namedValue. | +| `namedValueTags` | array | `[]` | Tags that when provided can be used to filter the NamedValue list. - string | +| `secret` | bool | `False` | Determines whether the value is a secret and should be encrypted or not. Default value is false. | +| `value` | string | `[newGuid()]` | Value of the NamedValue. Can contain policy expressions. It may not be empty or consist only of whitespace. This property will not be filled on 'GET' operations! Use '/listSecrets' POST request to get the value. | + + +### Parameter Usage: `keyVault` + +```json +"keyVault": { + "value":{ + "secretIdentifier":"Key vault secret identifier for fetching secret.", + "identityClientId":"SystemAssignedIdentity or UserAssignedIdentity Client ID which will be used to access key vault secret." + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the named value | +| `resourceGroupName` | string | The resource group the named value was deployed into | +| `resourceId` | string | The resource ID of the named value | + +## Template references + +- [Service/Namedvalues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/namedValues) diff --git a/carml/1.0.1/service/namedValues/version.json b/carml/1.0.1/service/namedValues/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/namedValues/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/carml/1.0.1/service/policies/deploy.bicep b/carml/1.0.1/service/policies/deploy.bicep new file mode 100644 index 000000000..3d537ef78 --- /dev/null +++ b/carml/1.0.1/service/policies/deploy.bicep @@ -0,0 +1,54 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. The name of the policy') +param name string = 'policy' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Format of the policyContent.') +@allowed([ + 'rawxml' + 'rawxml-link' + 'xml' + 'xml-link' +]) +param format string = 'xml' + +@description('Required. Contents of the Policy as defined by the format.') +param value string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource policy 'Microsoft.ApiManagement/service/policies@2021-08-01' = { + name: name + parent: service + properties: { + format: format + value: value + } +} + +@description('The resource ID of the API management service policy') +output resourceId string = policy.id + +@description('The name of the API management service policy') +output name string = policy.name + +@description('The resource group the API management service policy was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/policies/readme.md b/carml/1.0.1/service/policies/readme.md new file mode 100644 index 000000000..81622ca57 --- /dev/null +++ b/carml/1.0.1/service/policies/readme.md @@ -0,0 +1,44 @@ +# API Management Service Policies `[Microsoft.ApiManagement/service/policies]` + +This module deploys API Management Service Policy. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/policies` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `value` | string | Contents of the Policy as defined by the format. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `format` | string | `'xml'` | `[rawxml, rawxml-link, xml, xml-link]` | Format of the policyContent. | +| `name` | string | `'policy'` | | The name of the policy | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service policy | +| `resourceGroupName` | string | The resource group the API management service policy was deployed into | +| `resourceId` | string | The resource ID of the API management service policy | + +## Template references + +- [Service/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/policies) diff --git a/carml/1.0.1/service/policies/version.json b/carml/1.0.1/service/policies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/policies/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/carml/1.0.1/service/portalsettings/deploy.bicep b/carml/1.0.1/service/portalsettings/deploy.bicep new file mode 100644 index 000000000..d6bf5a736 --- /dev/null +++ b/carml/1.0.1/service/portalsettings/deploy.bicep @@ -0,0 +1,47 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. Portal setting name') +@allowed([ + 'delegation' + 'signin' + 'signup' +]) +param name string + +@description('Optional. Portal setting properties.') +param properties object = {} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource portalSetting 'Microsoft.ApiManagement/service/portalsettings@2021-08-01' = if (!empty(properties)) { + name: any(name) + parent: service + properties: properties +} + +@description('The resource ID of the API management service portal setting') +output resourceId string = portalSetting.id + +@description('The name of the API management service portal setting') +output name string = portalSetting.name + +@description('The resource group the API management service portal setting was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/portalsettings/readme.md b/carml/1.0.1/service/portalsettings/readme.md new file mode 100644 index 000000000..c7bc1923e --- /dev/null +++ b/carml/1.0.1/service/portalsettings/readme.md @@ -0,0 +1,43 @@ +# API Management Service Portal Settings `[Microsoft.ApiManagement/service/portalsettings]` + +This module deploys API Management Service Portal Setting. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/portalsettings` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `apiManagementServiceName` | string | | The name of the of the API Management service. | +| `name` | string | `[delegation, signin, signup]` | Portal setting name | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `properties` | object | `{object}` | Portal setting properties. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service portal setting | +| `resourceGroupName` | string | The resource group the API management service portal setting was deployed into | +| `resourceId` | string | The resource ID of the API management service portal setting | + +## Template references + +- ['service/portalsettings' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/service) diff --git a/carml/1.0.1/service/portalsettings/version.json b/carml/1.0.1/service/portalsettings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/portalsettings/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/carml/1.0.1/service/products/apis/deploy.bicep b/carml/1.0.1/service/products/apis/deploy.bicep new file mode 100644 index 000000000..2d5482ae3 --- /dev/null +++ b/carml/1.0.1/service/products/apis/deploy.bicep @@ -0,0 +1,45 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. The name of the of the Product.') +param productName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. Name of the product API.') +param name string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName + + resource product 'products@2021-04-01-preview' existing = { + name: productName + } +} + +resource api 'Microsoft.ApiManagement/service/products/apis@2021-08-01' = { + name: name + parent: service::product +} + +@description('The resource ID of the product API') +output resourceId string = api.id + +@description('The name of the product API') +output name string = api.name + +@description('The resource group the product API was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/products/apis/readme.md b/carml/1.0.1/service/products/apis/readme.md new file mode 100644 index 000000000..522e3c29d --- /dev/null +++ b/carml/1.0.1/service/products/apis/readme.md @@ -0,0 +1,43 @@ +# API Management Service Products APIs `[Microsoft.ApiManagement/service/products/apis]` + +This module deploys API Management Service Product APIs. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/products/apis` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `name` | string | Name of the product API. | +| `productName` | string | The name of the of the Product. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the product API | +| `resourceGroupName` | string | The resource group the product API was deployed into | +| `resourceId` | string | The resource ID of the product API | + +## Template references + +- [Service/Products/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/apis) diff --git a/carml/1.0.1/service/products/apis/version.json b/carml/1.0.1/service/products/apis/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/products/apis/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/carml/1.0.1/service/products/deploy.bicep b/carml/1.0.1/service/products/deploy.bicep new file mode 100644 index 000000000..804c12ab9 --- /dev/null +++ b/carml/1.0.1/service/products/deploy.bicep @@ -0,0 +1,95 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Whether subscription approval is required. If false, new subscriptions will be approved automatically enabling developers to call the products APIs immediately after subscribing. If true, administrators must manually approve the subscription before the developer can any of the products APIs. Can be present only if subscriptionRequired property is present and has a value of false.') +param approvalRequired bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Product description. May include HTML formatting tags.') +param productDescription string = '' + +@description('Optional. Array of Product APIs.') +param apis array = [] + +@description('Optional. Array of Product Groups.') +param groups array = [] + +@description('Required. Product Name.') +param name string + +@description('Optional. whether product is published or not. Published products are discoverable by users of developer portal. Non published products are visible only to administrators. Default state of Product is notPublished. - notPublished or published') +param state string = 'published' + +@description('Optional. Whether a product subscription is required for accessing APIs included in this product. If true, the product is referred to as "protected" and a valid subscription key is required for a request to an API included in the product to succeed. If false, the product is referred to as "open" and requests to an API included in the product can be made without a subscription key. If property is omitted when creating a new product it\'s value is assumed to be true.') +param subscriptionRequired bool = false + +@description('Optional. Whether the number of subscriptions a user can have to this product at the same time. Set to null or omit to allow unlimited per user subscriptions. Can be present only if subscriptionRequired property is present and has a value of false.') +param subscriptionsLimit int = 1 + +@description('Optional. Product terms of use. Developers trying to subscribe to the product will be presented and required to accept these terms before they can complete the subscription process.') +param terms string = '' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource product 'Microsoft.ApiManagement/service/products@2021-08-01' = { + name: name + parent: service + properties: { + description: productDescription + displayName: name + terms: terms + subscriptionRequired: subscriptionRequired + approvalRequired: subscriptionRequired ? approvalRequired : null + subscriptionsLimit: subscriptionRequired ? subscriptionsLimit : null + state: state + } +} + +module product_apis 'apis/deploy.bicep' = [for (api, index) in apis: { + name: '${deployment().name}-Api-${index}' + params: { + apiManagementServiceName: apiManagementServiceName + name: api.name + productName: name + } +}] + +module product_groups 'groups/deploy.bicep' = [for (group, index) in groups: { + name: '${deployment().name}-Group-${index}' + params: { + apiManagementServiceName: apiManagementServiceName + name: group.name + productName: name + } +}] + +@description('The resource ID of the API management service product') +output resourceId string = product.id + +@description('The name of the API management service product') +output name string = product.name + +@description('The resource group the API management service product was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The Resources IDs of the API management service product APIs') +output apiResourceIds array = [for index in range(0, length(apis)): product_apis[index].outputs.resourceId] + +@description('The Resources IDs of the API management service product groups') +output groupResourceIds array = [for index in range(0, length(groups)): product_groups[index].outputs.resourceId] diff --git a/carml/1.0.1/service/products/groups/deploy.bicep b/carml/1.0.1/service/products/groups/deploy.bicep new file mode 100644 index 000000000..410e7122d --- /dev/null +++ b/carml/1.0.1/service/products/groups/deploy.bicep @@ -0,0 +1,45 @@ +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Required. The name of the of the Product.') +param productName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. Name of the product group.') +param name string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName + + resource product 'products@2021-04-01-preview' existing = { + name: productName + } +} + +resource group 'Microsoft.ApiManagement/service/products/groups@2021-08-01' = { + name: name + parent: service::product +} + +@description('The resource ID of the product group') +output resourceId string = group.id + +@description('The name of the product group') +output name string = group.name + +@description('The resource group the product group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/products/groups/readme.md b/carml/1.0.1/service/products/groups/readme.md new file mode 100644 index 000000000..97bb4727c --- /dev/null +++ b/carml/1.0.1/service/products/groups/readme.md @@ -0,0 +1,43 @@ +# API Management Service Products Groups `[Microsoft.ApiManagement/service/products/groups]` + +This module deploys API Management Service Product Groups. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/products/groups` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `name` | string | Name of the product group. | +| `productName` | string | The name of the of the Product. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the product group | +| `resourceGroupName` | string | The resource group the product group was deployed into | +| `resourceId` | string | The resource ID of the product group | + +## Template references + +- [Service/Products/Groups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/groups) diff --git a/carml/1.0.1/service/products/groups/version.json b/carml/1.0.1/service/products/groups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/products/groups/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/carml/1.0.1/service/products/readme.md b/carml/1.0.1/service/products/readme.md new file mode 100644 index 000000000..61e35de65 --- /dev/null +++ b/carml/1.0.1/service/products/readme.md @@ -0,0 +1,62 @@ +# API Management Service Products `[Microsoft.ApiManagement/service/products]` + +This module deploys API Management Service Products. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/products` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/groups` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `name` | string | Product Name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `apis` | _[apis](apis/readme.md)_ array | `[]` | Array of Product APIs. | +| `approvalRequired` | bool | `False` | Whether subscription approval is required. If false, new subscriptions will be approved automatically enabling developers to call the products APIs immediately after subscribing. If true, administrators must manually approve the subscription before the developer can any of the products APIs. Can be present only if subscriptionRequired property is present and has a value of false. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `groups` | _[groups](groups/readme.md)_ array | `[]` | Array of Product Groups. | +| `productDescription` | string | `''` | Product description. May include HTML formatting tags. | +| `state` | string | `'published'` | whether product is published or not. Published products are discoverable by users of developer portal. Non published products are visible only to administrators. Default state of Product is notPublished. - notPublished or published | +| `subscriptionRequired` | bool | `False` | Whether a product subscription is required for accessing APIs included in this product. If true, the product is referred to as "protected" and a valid subscription key is required for a request to an API included in the product to succeed. If false, the product is referred to as "open" and requests to an API included in the product can be made without a subscription key. If property is omitted when creating a new product it's value is assumed to be true. | +| `subscriptionsLimit` | int | `1` | Whether the number of subscriptions a user can have to this product at the same time. Set to null or omit to allow unlimited per user subscriptions. Can be present only if subscriptionRequired property is present and has a value of false. | +| `terms` | string | `''` | Product terms of use. Developers trying to subscribe to the product will be presented and required to accept these terms before they can complete the subscription process. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `apiResourceIds` | array | The Resources IDs of the API management service product APIs | +| `groupResourceIds` | array | The Resources IDs of the API management service product groups | +| `name` | string | The name of the API management service product | +| `resourceGroupName` | string | The resource group the API management service product was deployed into | +| `resourceId` | string | The resource ID of the API management service product | + +## Template references + +- [Service/Products](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products) +- [Service/Products/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/apis) +- [Service/Products/Groups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/groups) diff --git a/carml/1.0.1/service/products/version.json b/carml/1.0.1/service/products/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/products/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/carml/1.0.1/service/readme.md b/carml/1.0.1/service/readme.md new file mode 100644 index 000000000..6f571af30 --- /dev/null +++ b/carml/1.0.1/service/readme.md @@ -0,0 +1,190 @@ +# API Management Services `[Microsoft.ApiManagement/service]` + +This module deploys an API management service. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apis/policies` | 2021-08-01 | +| `Microsoft.ApiManagement/service/apiVersionSets` | 2021-08-01 | +| `Microsoft.ApiManagement/service/authorizationServers` | 2021-08-01 | +| `Microsoft.ApiManagement/service/backends` | 2021-08-01 | +| `Microsoft.ApiManagement/service/caches` | 2021-08-01 | +| `Microsoft.ApiManagement/service/identityProviders` | 2021-08-01 | +| `Microsoft.ApiManagement/service/namedValues` | 2021-08-01 | +| `Microsoft.ApiManagement/service/policies` | 2021-08-01 | +| `Microsoft.ApiManagement/service/portalsettings` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/apis` | 2021-08-01 | +| `Microsoft.ApiManagement/service/products/groups` | 2021-08-01 | +| `Microsoft.ApiManagement/service/subscriptions` | 2021-08-01 | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the of the API Management service. | +| `publisherEmail` | string | The email address of the owner of the service. | +| `publisherName` | string | The name of the owner of the service. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalLocations` | array | `[]` | | Additional datacenter locations of the API Management service. | +| `apis` | _[apis](apis/readme.md)_ array | `[]` | | APIs. | +| `apiVersionSets` | _[apiVersionSets](apiVersionSets/readme.md)_ array | `[]` | | API Version Sets. | +| `authorizationServers` | _[authorizationServers](authorizationServers/readme.md)_ array | `[]` | | Authorization servers. | +| `backends` | _[backends](backends/readme.md)_ array | `[]` | | Backends. | +| `caches` | _[caches](caches/readme.md)_ array | `[]` | | Caches. | +| `certificates` | array | `[]` | | List of Certificates that need to be installed in the API Management service. Max supported certificates that can be installed is 10. | +| `customProperties` | object | `{object}` | | Custom properties of the API Management service. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[GatewayLogs]` | `[GatewayLogs]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disableGateway` | bool | `False` | | Property only valid for an API Management service deployed in multiple locations. This can be used to disable the gateway in master region. | +| `enableClientCertificate` | bool | `False` | | Property only meant to be used for Consumption SKU Service. This enforces a client certificate to be presented on each request to the gateway. This also enables the ability to authenticate the certificate in the policy on the gateway. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hostnameConfigurations` | array | `[]` | | Custom hostname configuration of the API Management service. | +| `identityProviders` | _[identityProviders](identityProviders/readme.md)_ array | `[]` | | Identity providers. | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `minApiVersion` | string | `''` | | Limit control plane API calls to API Management service with version equal to or newer than this value. | +| `namedValues` | _[namedValues](namedValues/readme.md)_ array | `[]` | | Named values. | +| `newGuidValue` | string | `[newGuid()]` | | Necessary to create a new GUID. | +| `notificationSenderEmail` | string | `'apimgmt-noreply@mail.windowsazure.com'` | | The notification sender email address for the service. | +| `policies` | _[policies](policies/readme.md)_ array | `[]` | | Policies. | +| `portalSettings` | _[portalSettings](portalSettings/readme.md)_ array | `[]` | | Portal settings. | +| `products` | _[products](products/readme.md)_ array | `[]` | | Products. | +| `restore` | bool | `False` | | Undelete API Management Service if it was previously soft-deleted. If this flag is specified and set to True all other properties will be ignored. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'Developer'` | `[Consumption, Developer, Basic, Standard, Premium]` | The pricing tier of this API Management service. | +| `skuCount` | int | `1` | `[1, 2]` | The instance size of this API Management service. | +| `subnetResourceId` | string | `''` | | The full resource ID of a subnet in a virtual network to deploy the API Management service in. | +| `subscriptions` | _[subscriptions](subscriptions/readme.md)_ array | `[]` | | Subscriptions. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `virtualNetworkType` | string | `'None'` | `[None, External, Internal]` | The type of VPN in which API Management service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only. | +| `zones` | array | `[]` | | A list of availability zones denoting where the resource needs to come from. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `apiManagementServicePolicy` + +```Json +"apiManagementServicePolicy": { + "value": { + "value":" ", + "format":"xml" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service | +| `resourceGroupName` | string | The resource group the API management service was deployed into | +| `resourceId` | string | The resource ID of the API management service | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +- *None* + +## Template references + +- ['service/portalsettings' Parent Documentation](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/service) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Service](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service) +- [Service/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis) +- [Service/Apis/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apis/policies) +- [Service/Apiversionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/apiVersionSets) +- [Service/Authorizationservers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/authorizationServers) +- [Service/Backends](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/backends) +- [Service/Caches](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/caches) +- [Service/Identityproviders](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/identityProviders) +- [Service/Namedvalues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/namedValues) +- [Service/Policies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/policies) +- [Service/Products](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products) +- [Service/Products/Apis](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/apis) +- [Service/Products/Groups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/products/groups) +- [Service/Subscriptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/subscriptions) diff --git a/carml/1.0.1/service/subscriptions/deploy.bicep b/carml/1.0.1/service/subscriptions/deploy.bicep new file mode 100644 index 000000000..477bde8cd --- /dev/null +++ b/carml/1.0.1/service/subscriptions/deploy.bicep @@ -0,0 +1,65 @@ +@description('Optional. Determines whether tracing can be enabled.') +param allowTracing bool = true + +@description('Required. The name of the of the API Management service.') +param apiManagementServiceName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. User (user ID path) for whom subscription is being created in form /users/{userId}') +param ownerId string = '' + +@description('Optional. Primary subscription key. If not specified during request key will be generated automatically.') +param primaryKey string = '' + +@description('Optional. Scope type to choose between a product, "allAPIs" or a specific API. Scope like "/products/{productId}" or "/apis" or "/apis/{apiId}".') +param scope string = '/apis' + +@description('Optional. Secondary subscription key. If not specified during request key will be generated automatically.') +param secondaryKey string = '' + +@description('Optional. Initial subscription state. If no value is specified, subscription is created with Submitted state. Possible states are "*" active "?" the subscription is active, "*" suspended "?" the subscription is blocked, and the subscriber cannot call any APIs of the product, * submitted ? the subscription request has been made by the developer, but has not yet been approved or rejected, * rejected ? the subscription request has been denied by an administrator, * cancelled ? the subscription has been cancelled by the developer or administrator, * expired ? the subscription reached its expiration date and was deactivated. - suspended, active, expired, submitted, rejected, cancelled') +param state string = '' + +@description('Required. Subscription name.') +param name string + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = { + name: apiManagementServiceName +} + +resource subscription 'Microsoft.ApiManagement/service/subscriptions@2021-08-01' = { + name: name + parent: service + properties: { + scope: scope + displayName: name + ownerId: !empty(ownerId) ? ownerId : null + primaryKey: !empty(primaryKey) ? primaryKey : null + secondaryKey: !empty(secondaryKey) ? secondaryKey : null + state: !empty(state) ? state : null + allowTracing: allowTracing + } +} + +@description('The resource ID of the API management service subscription') +output resourceId string = subscription.id + +@description('The name of the API management service subscription') +output name string = subscription.name + +@description('The resource group the API management service subscription was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.0.1/service/subscriptions/readme.md b/carml/1.0.1/service/subscriptions/readme.md new file mode 100644 index 000000000..aeb4a0d70 --- /dev/null +++ b/carml/1.0.1/service/subscriptions/readme.md @@ -0,0 +1,54 @@ +# API Management Subscriptions `[Microsoft.ApiManagement/service/subscriptions]` + +This module deploys API Management Subscriptions. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ApiManagement/service/subscriptions` | 2021-08-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.ApiManagement/service` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `apiManagementServiceName` | string | The name of the of the API Management service. | +| `name` | string | Subscription name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `allowTracing` | bool | `True` | Determines whether tracing can be enabled. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ownerId` | string | `''` | User (user ID path) for whom subscription is being created in form /users/{userId} | +| `primaryKey` | string | `''` | Primary subscription key. If not specified during request key will be generated automatically. | +| `scope` | string | `'/apis'` | Scope type to choose between a product, "allAPIs" or a specific API. Scope like "/products/{productId}" or "/apis" or "/apis/{apiId}". | +| `secondaryKey` | string | `''` | Secondary subscription key. If not specified during request key will be generated automatically. | +| `state` | string | `''` | Initial subscription state. If no value is specified, subscription is created with Submitted state. Possible states are "*" active "?" the subscription is active, "*" suspended "?" the subscription is blocked, and the subscriber cannot call any APIs of the product, * submitted ? the subscription request has been made by the developer, but has not yet been approved or rejected, * rejected ? the subscription request has been denied by an administrator, * cancelled ? the subscription has been cancelled by the developer or administrator, * expired ? the subscription reached its expiration date and was deactivated. - suspended, active, expired, submitted, rejected, cancelled | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the API management service subscription | +| `resourceGroupName` | string | The resource group the API management service subscription was deployed into | +| `resourceId` | string | The resource ID of the API management service subscription | + +## Template references + +- [Service/Subscriptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ApiManagement/2021-08-01/service/subscriptions) diff --git a/carml/1.0.1/service/subscriptions/version.json b/carml/1.0.1/service/subscriptions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/subscriptions/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/carml/1.0.1/service/version.json b/carml/1.0.1/service/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.0.1/service/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..7271e1d83 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json new file mode 100644 index 000000000..f140b8c7e --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..de4e5052a --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json new file mode 100644 index 000000000..e28b39cfd --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..ebadf2e43 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/sub.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": { + "name": { + "value": "<>-min-sub-polAss" + }, + "policyDefinitionID": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json new file mode 100644 index 000000000..cc671f092 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/.parameters/sub.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": "<>-sub-polAss" + }, + "displayName": { + "value": "[Display Name] Policy Assignment at the subscription scope" + }, + "description": { + "value": "[Description] Policy Assignment at the subscription 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" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policyAssignments/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyAssignments/deploy.bicep new file mode 100644 index 000000000..2f4761e3c --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/deploy.bicep @@ -0,0 +1,143 @@ +targetScope = 'managementGroup' + +@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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment') +param subscriptionId string = '' + +@sys.description('Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment') +param resourceGroupName string = '' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policyAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + managementGroupId: managementGroupId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module policyAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + subscriptionId: subscriptionId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module policyAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyAssignment-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + name: name + policyDefinitionId: policyDefinitionId + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + parameters: !empty(parameters) ? parameters : {} + identity: identity + roleDefinitionIds: !empty(roleDefinitionIds) ? roleDefinitionIds : [] + metadata: !empty(metadata) ? metadata : {} + nonComplianceMessage: !empty(nonComplianceMessage) ? nonComplianceMessage : '' + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + subscriptionId: subscriptionId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@sys.description('Policy Assignment 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(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(subscriptionId) && empty(resourceGroupName) ? policyAssignment_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_sub.outputs.resourceId : policyAssignment_rg.outputs.resourceId) diff --git a/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep new file mode 100644 index 000000000..9f6d4b94b --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep @@ -0,0 +1,108 @@ +targetScope = 'managementGroup' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +var nonComplianceMessage_var = { + message: !empty(nonComplianceMessage) ? nonComplianceMessage : null +} + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(managementGroupId, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@sys.description('Policy Assignment resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyAssignments', policyAssignment.name) diff --git a/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/readme.md new file mode 100644 index 000000000..842e05c93 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/readme.md @@ -0,0 +1,55 @@ +# Policy Assignment on Management Group level `[Microsoft.Authorization/policyAssignments/managementGroup]` + +With this module you can perform policy assignments on a management group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Location for all resources. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | + + +## 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/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/version.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/readme.md b/carml/1.2.0/Microsoft.Authorization/policyAssignments/readme.md new file mode 100644 index 000000000..194aebc90 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/readme.md @@ -0,0 +1,116 @@ +# Policy Assignments `[Microsoft.Authorization/policyAssignments]` + +With this module you can perform policy assignments across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope, 64 characters for subscription and resource group scopes. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Location for all resources. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | +| `resourceGroupName` | string | `''` | | The Target Scope for the Policy. The name of the resource group for the policy assignment | +| `subscriptionId` | string | `''` | | The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `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/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep new file mode 100644 index 000000000..6eaf1e635 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep @@ -0,0 +1,113 @@ +targetScope = 'resourceGroup' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +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. 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. If not provided, will use the current scope for deployment.') +param resourceGroupName string = resourceGroup().name + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(subscriptionId, resourceGroupName, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@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/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md new file mode 100644 index 000000000..14c90f1d2 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md @@ -0,0 +1,57 @@ +# Policy Assignment on Resource Group level `[Microsoft.Authorization/policyAssignments/resourceGroup]` + +With this module you can perform policy assignments on a resource group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 64 characters for resource group scope. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `metadata` | object | `{object}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | 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. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/version.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep new file mode 100644 index 000000000..93824ae2b --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep @@ -0,0 +1,108 @@ +targetScope = 'subscription' + +@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. 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 + +@sys.description('Optional. Parameters for the policy assignment if needed.') +param parameters object = {} + +@sys.description('Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning \'Modify\' policy definitions.') +@allowed([ + 'SystemAssigned' + 'None' +]) +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 policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The messages that describe why a resource is non-compliant with the policy.') +param nonComplianceMessage string = '' + +@sys.description('Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce') +@allowed([ + 'Default' + 'DoNotEnforce' +]) +param enforcementMode string = 'Default' + +@sys.description('Optional. The policy excluded scopes') +param notScopes array = [] + +@sys.description('Optional. Location for all resources.') +param location string = deployment().location + +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. If not provided, will use the current scope for deployment.') +param subscriptionId string = subscription().subscriptionId + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var identity_var = identity == 'SystemAssigned' ? { + type: identity +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { + name: name + location: location + properties: { + displayName: !empty(displayName) ? displayName : null + metadata: !empty(metadata) ? metadata : null + description: !empty(description) ? description : null + policyDefinitionId: policyDefinitionId + parameters: parameters + nonComplianceMessages: !empty(nonComplianceMessage) ? array(nonComplianceMessage_var) : [] + enforcementMode: enforcementMode + notScopes: !empty(notScopes) ? notScopes : [] + } + identity: identity_var +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity != 'None') { + name: guid(subscriptionId, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignment.identity.principalId + principalType: 'ServicePrincipal' + } +}] + +@sys.description('Policy Assignment Name') +output name string = policyAssignment.name + +@sys.description('Policy Assignment principal ID') +output principalId string = identity == 'SystemAssigned' ? policyAssignment.identity.principalId : '' + +@sys.description('Policy Assignment resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyAssignments', policyAssignment.name) diff --git a/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/readme.md b/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/readme.md new file mode 100644 index 000000000..24bde8974 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/readme.md @@ -0,0 +1,55 @@ +# Policy Assignment on Subscription level `[Microsoft.Authorization/policyAssignments/subscription]` + +With this module you can perform policy assignments on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy assignment. Maximum length is 64 characters for subscription scope. | +| `policyDefinitionId` | string | Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | This message will be part of response in case of policy violation. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforcementMode` | string | `'Default'` | `[Default, DoNotEnforce]` | The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `'SystemAssigned'` | `[SystemAssigned, None]` | The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Location for all resources. | +| `metadata` | object | `{object}` | | The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `nonComplianceMessage` | string | `''` | | The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | The policy excluded scopes | +| `parameters` | object | `{object}` | | Parameters for the policy assignment if needed. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/version.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyAssignments/version.json b/carml/1.2.0/Microsoft.Authorization/policyAssignments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyAssignments/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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..431a0f6f5 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..7196de615 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..f2cd03cfb --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-sub-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" + } + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..e44512751 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/.parameters/sub.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": "<>-sub-policyDef" + }, + "displayName": { + "value": "[DisplayName] This policy definition is deployed at subscription scope" + }, + "description": { + "value": "[Description] This policy definition is deployed at subscription 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" + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policyDefinitions/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/deploy.bicep new file mode 100644 index 000000000..c88c0a795 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/deploy.bicep @@ -0,0 +1,99 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +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). 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 = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policyDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + managementGroupId: managementGroupId + mode: mode + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyRule: policyRule + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module policyDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + subscriptionId: subscriptionId + mode: mode + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyRule: policyRule + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@sys.description('Policy Definition Name') +output name string = empty(subscriptionId) ? policyDefinition_mg.outputs.name : policyDefinition_sub.outputs.name + +@sys.description('Policy Definition resource ID') +output resourceId string = empty(subscriptionId) ? policyDefinition_mg.outputs.resourceId : policyDefinition_sub.outputs.resourceId + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = empty(subscriptionId) ? policyDefinition_mg.outputs.roleDefinitionIds : policyDefinition_sub.outputs.roleDefinitionIds diff --git a/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..c577623b5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +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. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + mode: mode + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = policyDefinition.name + +@sys.description('Policy Definition resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyDefinitions', policyDefinition.name) + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = (contains(policyDefinition.properties.policyRule.then, 'details') ? ((contains(policyDefinition.properties.policyRule.then.details, 'roleDefinitionIds') ? policyDefinition.properties.policyRule.then.details.roleDefinitionIds : [])) : []) diff --git a/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..97c0d07e7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md @@ -0,0 +1,49 @@ +# Policy Definitions on Management Group level `[Microsoft.Authorization/policyDefinitions/managementGroup]` + +With this module you can create policy definitions on a management group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy definition. Maximum length is 64 characters. | +| `policyRule` | object | The Policy Rule details for the Policy Definition | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The policy definition description. | +| `displayName` | string | `''` | | The display name of the policy definition. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | The group ID of the Management Group. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | 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]` | The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `parameters` | object | `{object}` | | The policy definition parameters that can be used in policy definition references. | + + +## 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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/version.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/readme.md b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/readme.md new file mode 100644 index 000000000..8c39b11cc --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/readme.md @@ -0,0 +1,94 @@ +# Policy Definitions `[Microsoft.Authorization/policyDefinitions]` + +With this module you can create policy definitions across the management group or subscription scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy definition. Maximum length is 64 characters for management group scope and subscription scope. | +| `policyRule` | object | The Policy Rule details for the Policy Definition | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The policy definition description. | +| `displayName` | string | `''` | | The display name of the policy definition. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | 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]` | The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `parameters` | object | `{object}` | | The policy definition parameters that can be used in policy definition references. | +| `subscriptionId` | string | `''` | | The subscription ID of the subscription (Scope). Cannot be used with managementGroupId | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +## 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 | +| :-- | :-- | :-- | +| `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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..46b723022 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'subscription' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The policy definition description.') +param description string = '' + +@sys.description('Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data.') +@allowed([ + 'All' + 'Indexed' + 'Microsoft.KeyVault.Data' + 'Microsoft.ContainerService.Data' + 'Microsoft.Kubernetes.Data' +]) +param mode string = 'All' + +@sys.description('Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy definition parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Required. The Policy Rule details for the Policy Definition') +param policyRule object + +@sys.description('Optional. The subscription ID of the subscription') +param subscriptionId string = subscription().subscriptionId + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + mode: mode + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyRule: policyRule + } +} + +@sys.description('Policy Definition Name') +output name string = policyDefinition.name + +@sys.description('Policy Definition resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyDefinitions', policyDefinition.name) + +@sys.description('Policy Definition Role Definition IDs') +output roleDefinitionIds array = (contains(policyDefinition.properties.policyRule.then, 'details') ? ((contains(policyDefinition.properties.policyRule.then.details, 'roleDefinitionIds') ? policyDefinition.properties.policyRule.then.details.roleDefinitionIds : [])) : []) diff --git a/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/readme.md b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/readme.md new file mode 100644 index 000000000..3c527a4a1 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/readme.md @@ -0,0 +1,49 @@ +# Policy Definitions on Subscription level `[Microsoft.Authorization/policyDefinitions/subscription]` + +With this module you can create policy definitions on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy definition. Maximum length is 64 characters. | +| `policyRule` | object | The Policy Rule details for the Policy Definition | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The policy definition description. | +| `displayName` | string | `''` | | The display name of the policy definition. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `metadata` | object | `{object}` | | 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]` | The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `parameters` | object | `{object}` | | The policy definition parameters that can be used in policy definition references. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/version.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyDefinitions/version.json b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyDefinitions/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..f5816fcd6 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json new file mode 100644 index 000000000..2c76ecb64 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..2573b17fe --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json new file mode 100644 index 000000000..68fda77de --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..920e7d2ad --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/sub.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": { + "name": { + "value": "<>-min-sub-polexem" + }, + "policyAssignmentId": { + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json new file mode 100644 index 000000000..02b3e9037 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/.parameters/sub.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": "<>-sub-polexem" + }, + "displayName": { + "value": "[Display Name] policy exempt (subscription 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": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policyExemptions/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyExemptions/deploy.bicep new file mode 100644 index 000000000..643376d62 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/deploy.bicep @@ -0,0 +1,122 @@ +targetScope = 'managementGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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 = '' + +@sys.description('Optional. The name of the resource group to be exempted from the policy assignment. Must also use the subscription ID parameter.') +param resourceGroupName string = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policyExemption_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + managementGroupId: managementGroupId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module policyExemption_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + subscriptionId: subscriptionId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module policyExemption_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicyExemption-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : '' + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@sys.description('Policy Exemption 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(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(subscriptionId) && empty(resourceGroupName) ? policyExemption_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_sub.outputs.scope : policyExemption_rg.outputs.scope) diff --git a/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep new file mode 100644 index 000000000..2e79abcdd --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'managementGroup' + +@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 assignment. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@sys.description('Policy Exemption Scope') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) diff --git a/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/readme.md new file mode 100644 index 000000000..cdab3c4be --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/readme.md @@ -0,0 +1,50 @@ +# Policy Exemptions on Management Group level `[Microsoft.Authorization/policyExemptions/managementGroup]` + +With this module you can create policy exemptions on a management group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for management group scope. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy assignment. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | 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/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/version.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/readme.md b/carml/1.2.0/Microsoft.Authorization/policyExemptions/readme.md new file mode 100644 index 000000000..db8f04514 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/readme.md @@ -0,0 +1,116 @@ +# Policy Exemptions `[Microsoft.Authorization/policyExemptions]` + +With this module you can create policy exemptions across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for management group, subscription and resource group scopes. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy exemption. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | 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}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `resourceGroupName` | string | `''` | | The name of the resource group to be exempted from the policy assignment. Must also use the subscription ID parameter. | +| `subscriptionId` | string | `''` | | The subscription ID of the subscription to be exempted from the policy assignment. Cannot use with management group ID parameter. | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | Policy Exemption Name | +| `resourceId` | string | Policy Exemption resource ID | +| `scope` | string | Policy Exemption Scope | + +## Considerations + +- Policy Exemptions have a dependency on Policy Assignments being applied before creating an exemption. You can use the Policy Assignment [Module](../policyAssignments/deploy.bicep) to deploy a Policy Assignment and then create the exemption for it on the required scope. + +## Template references + +- [Policyexemptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-07-01-preview/policyExemptions) diff --git a/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep new file mode 100644 index 000000000..8551f2bb9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep @@ -0,0 +1,77 @@ +targetScope = 'resourceGroup' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. 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. If not provided, will use the current scope for deployment.') +param resourceGroupName string = resourceGroup().name + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = az.resourceId(subscriptionId, resourceGroupName, 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@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/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md new file mode 100644 index 000000000..cb8847d10 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md @@ -0,0 +1,51 @@ +# Policy Exemptions on Resource Group level `[Microsoft.Authorization/policyExemptions/resourceGroup]` + +With this module you can create policy exemptions on a resource group level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for resource group scope. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy exemption. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | 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]` | | 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/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/version.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep new file mode 100644 index 000000000..0106c0b91 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep @@ -0,0 +1,75 @@ +targetScope = 'subscription' + +@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. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +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. If not provided, will use the current scope for deployment.') +param subscriptionId string = subscription().subscriptionId + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { + name: name + properties: { + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + exemptionCategory: exemptionCategory + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : [] + expiresOn: !empty(expiresOn) ? expiresOn : null + } +} + +@sys.description('Policy Exemption Name') +output name string = policyExemption.name + +@sys.description('Policy Exemption resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policyExemptions', policyExemption.name) + +@sys.description('Policy Exemption Scope') +output scope string = subscription().id diff --git a/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/readme.md b/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/readme.md new file mode 100644 index 000000000..e64dcf176 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/readme.md @@ -0,0 +1,50 @@ +# Policy Exemptions on Subscription level `[Microsoft.Authorization/policyExemptions/subscription]` + +With this module you can create policy exemptions on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy exemption. Maximum length is 64 characters for subscription scope. | +| `policyAssignmentId` | string | The resource ID of the policy assignment that is being exempted. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | `''` | | The description of the policy exemption. | +| `displayName` | string | `''` | | The display name of the policy exemption. Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `exemptionCategory` | string | `'Mitigated'` | `[Mitigated, Waiver]` | The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | `''` | | 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]` | | Location deployment metadata. | +| `metadata` | object | `{object}` | | The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `policyDefinitionReferenceIds` | array | `[]` | | The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/version.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policyExemptions/version.json b/carml/1.2.0/Microsoft.Authorization/policyExemptions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policyExemptions/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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..92f9d4ac2 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..029e2d47c --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..f6a7e68f6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-sub-min-policySet" + }, + "policyDefinitions": { + "value": [ + { + "parameters": { + "listOfAllowedLocations": { + "value": [ + "australiaeast" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c" + } + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..16a92428b --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/.parameters/sub.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": "<>-sub-policySet" + }, + "displayName": { + "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": [ + { + "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" + } + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/deploy.bicep new file mode 100644 index 000000000..9bf774e6d --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/deploy.bicep @@ -0,0 +1,89 @@ +targetScope = 'managementGroup' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@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). 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 = '' + +@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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module policySetDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + managementGroupId: managementGroupId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module policySetDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + name: name + displayName: !empty(displayName) ? displayName : '' + description: !empty(description) ? description : '' + metadata: !empty(metadata) ? metadata : {} + parameters: !empty(parameters) ? parameters : {} + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + subscriptionId: subscriptionId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@sys.description('Policy Set Definition 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(subscriptionId) ? policySetDefinition_mg.outputs.resourceId : policySetDefinition_sub.outputs.resourceId diff --git a/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..3e6ab1886 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,65 @@ +targetScope = 'managementGroup' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description name of the Set Definition (Initiative)') +param description 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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policySetDefinition 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + } +} + +@sys.description('Policy Set Definition Name') +output name string = policySetDefinition.name + +@sys.description('Policy Set Definition resource ID') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/policySetDefinitions', policySetDefinition.name) diff --git a/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..44cca5380 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md @@ -0,0 +1,48 @@ +# 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. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope. | +| `policyDefinitions` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description name of the Set Definition (Initiative) | +| `displayName` | string | `''` | The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | The group ID of the Management Group. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `parameters` | object | `{object}` | The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | + + +## 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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/readme.md b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/readme.md new file mode 100644 index 000000000..313094f8f --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/readme.md @@ -0,0 +1,98 @@ +# Policy Set Definitions `[Microsoft.Authorization/policySetDefinitions]` + +With this module you can create policy set definitions across the management group or subscription scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope and 64 characters for subscription scope. | +| `policyDefinitions` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description name of the Set Definition (Initiative) | +| `displayName` | string | `''` | The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `parameters` | object | `{object}` | The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | +| `subscriptionId` | string | `''` | The subscription ID of the subscription (Scope). Cannot be used with managementGroupId | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +## 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 | +| :-- | :-- | :-- | +| `name` | string | Policy Set Definition Name | +| `resourceId` | string | Policy Set Definition resource ID | + +## Considerations + +- Policy Set Definitions (Initiatives) have a dependency on Policy Assignments being applied before creating an initiative. You can use the Policy Assignment [Module](../policyDefinitions/deploy.bicep) to deploy a Policy Definition and then create an initiative for it on the required scope. + +## Template references + +- [Policysetdefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policySetDefinitions) diff --git a/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..cf269aa4b --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep @@ -0,0 +1,65 @@ +targetScope = 'subscription' + +@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). Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description name of the Set Definition (Initiative)') +param description string = '' + +@sys.description('Optional. The subscription ID of the subscription') +param subscriptionId string = subscription().subscriptionId + +@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 = {} + +@sys.description('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') +param policyDefinitions array + +@sys.description('Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative).') +param policyDefinitionGroups array = [] + +@sys.description('Optional. The Set Definition (Initiative) parameters that can be used in policy definition references.') +param parameters object = {} + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource policySetDefinition 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = { + name: name + properties: { + policyType: 'Custom' + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + metadata: !empty(metadata) ? metadata : null + parameters: !empty(parameters) ? parameters : null + policyDefinitions: policyDefinitions + policyDefinitionGroups: !empty(policyDefinitionGroups) ? policyDefinitionGroups : [] + } +} + +@sys.description('Policy Set Definition Name') +output name string = policySetDefinition.name + +@sys.description('Policy Set Definition resource ID') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/policySetDefinitions', policySetDefinition.name) diff --git a/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/readme.md b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/readme.md new file mode 100644 index 000000000..3c4bf8fe0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/readme.md @@ -0,0 +1,48 @@ +# Policy Set Definitions on Subscription level `[Microsoft.Authorization/policySetDefinitions/subscription]` + +With this module you can create policy set definitions on a subscription level. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Specifies the name of the policy Set Definition (Initiative). Maximum length is 64 characters for subscription scope. | +| `policyDefinitions` | array | 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 | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `description` | string | `''` | The description name of the Set Definition (Initiative) | +| `displayName` | string | `''` | The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `metadata` | object | `{object}` | The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `parameters` | object | `{object}` | The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | +| `subscriptionId` | string | `[subscription().subscriptionId]` | 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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/version.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/version.json b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/policySetDefinitions/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..02a409875 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json new file mode 100644 index 000000000..e6362b62a --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..6011dc7e9 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json new file mode 100644 index 000000000..faf9fc3d9 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..2a90f97fb --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/sub.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": { + "roleDefinitionIdOrName": { + "value": "Storage Queue Data Reader" + }, + "principalId": { + "value": "<>" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json new file mode 100644 index 000000000..346ba64c0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/.parameters/sub.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 (subscription scope)" + }, + "principalId": { + "value": "<>" + }, + "principalType": { + "value": "ServicePrincipal" + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/roleAssignments/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleAssignments/deploy.bicep new file mode 100644 index 000000000..afe59e9d9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/deploy.bicep @@ -0,0 +1,121 @@ +targetScope = 'managementGroup' + +@sys.description('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\'') +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 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 not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name + +@sys.description('Optional. Location deployment metadata.') +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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module roleAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-MG-Module' + scope: managementGroup(managementGroupId) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + managementGroupId: managementGroupId + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module roleAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-Sub-Module' + scope: subscription(subscriptionId) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + subscriptionId: subscriptionId + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module roleAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-RoleAssignment-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + roleDefinitionIdOrName: roleDefinitionIdOrName + principalId: principalId + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + description: !empty(description) ? description : '' + principalType: !empty(principalType) ? principalType : '' + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : '' + conditionVersion: conditionVersion + condition: !empty(condition) ? condition : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@sys.description('The GUID of the Role Assignment') +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(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(subscriptionId) && empty(resourceGroupName) ? roleAssignment_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_sub.outputs.scope : roleAssignment_rg.outputs.scope) diff --git a/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep new file mode 100644 index 000000000..1226036c2 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep @@ -0,0 +1,363 @@ +targetScope = 'managementGroup' + +@sys.description('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\'') +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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(managementGroupId, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) + +@sys.description('The scope this Role Assignment applies to') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/roleAssignments', roleAssignment.name) diff --git a/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/readme.md new file mode 100644 index 000000000..649f825bc --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/readme.md @@ -0,0 +1,49 @@ +# Role Assignment on Management Group level `[Microsoft.Authorization/roleAssignments/managementGroup]` + +With this module you can perform role assignments on a management group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | + + +## 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/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/version.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/readme.md b/carml/1.2.0/Microsoft.Authorization/roleAssignments/readme.md new file mode 100644 index 000000000..f5b19e511 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/readme.md @@ -0,0 +1,115 @@ +# Role Assignments `[Microsoft.Authorization/roleAssignments]` + +This module deploys Role Assignments across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | | Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | +| `resourceGroupName` | string | `''` | | 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. | +| `subscriptionId` | string | `''` | | 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. | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Assignment | +| `resourceId` | string | The resource ID of the Role Assignment | +| `scope` | string | The scope this Role Assignment applies to | + +## Considerations + +This module can be deployed at the management group, subscription or resource group level + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep new file mode 100644 index 000000000..7e2144146 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep @@ -0,0 +1,365 @@ +targetScope = 'resourceGroup' + +@sys.description('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\'') +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 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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(subscriptionId, resourceGroupName, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +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/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md new file mode 100644 index 000000000..2aa023c01 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md @@ -0,0 +1,50 @@ +# Role Assignment on Resource Group level `[Microsoft.Authorization/roleAssignments/resourceGroup]` + +With this module you can perform role assignments on a resource group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/version.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep new file mode 100644 index 000000000..d6569d6fa --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep @@ -0,0 +1,363 @@ +targetScope = 'subscription' + +@sys.description('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\'') +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. 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') +param delegatedManagedIdentityResourceId string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') +param condition string = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Version of the condition. Currently accepted value is "2.0"') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +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' + 'AcrPull': '/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d' + 'AcrImageSigner': '/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f' + 'AcrDelete': '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' + 'AcrQuarantineReader': '/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04' + 'AcrQuarantineWriter': '/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608' + 'API Management Service Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61' + 'API Management Service Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d' + 'Application Insights Component Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e' + 'Application Insights Snapshot Debugger': '/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b' + 'Attestation Reader': '/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3' + 'Automation Job Operator': '/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f' + 'Automation Runbook Operator': '/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5' + 'Automation Operator': '/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404' + 'Avere Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a' + 'Avere Operator': '/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9' + 'Azure Kubernetes Service Cluster Admin Role': '/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8' + 'Azure Kubernetes Service Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f' + 'Azure Maps Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa' + 'Azure Stack Registration Owner': '/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a' + 'Backup Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b' + 'Billing Reader': '/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64' + 'Backup Operator': '/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324' + 'Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912' + 'BizTalk Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342' + 'CDN Endpoint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45' + 'CDN Endpoint Reader': '/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd' + 'CDN Profile Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432' + 'CDN Profile Reader': '/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af' + 'Classic Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f' + 'Classic Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25' + 'Classic Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d' + 'ClearDB MySQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe' + 'Classic Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb' + 'Cognitive Services User': '/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908' + 'Cognitive Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + 'CosmosBackupOperator': '/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb' + 'Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + 'Cosmos DB Account Reader Role': '/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8' + 'Cost Management Contributor': '/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430' + 'Cost Management Reader': '/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3' + 'Data Box Contributor': '/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5' + 'Data Box Reader': '/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027' + 'Data Factory Contributor': '/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5' + 'Data Purger': '/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90' + 'Data Lake Analytics Developer': '/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88' + 'DevTest Labs User': '/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64' + 'DocumentDB Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450' + 'DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314' + 'EventGrid EventSubscription Contributor': '/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443' + 'EventGrid EventSubscription Reader': '/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405' + 'Graph Owner': '/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9' + 'HDInsight Domain Services Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c' + 'Intelligent Systems Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e' + 'Key Vault Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395' + 'Knowledge Consumer': '/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c' + 'Lab Creator': '/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead' + 'Log Analytics Reader': '/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893' + 'Log Analytics Contributor': '/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293' + 'Logic App Operator': '/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe' + 'Logic App Contributor': '/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' + 'Managed Identity Operator': '/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + 'Managed Identity Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59' + 'Management Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c' + 'Management Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d' + 'Monitoring Metrics Publisher': '/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb' + 'Monitoring Reader': '/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05' + 'Network Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7' + 'Monitoring Contributor': '/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa' + 'New Relic APM Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237' + 'Owner': '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + 'Reader': '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Redis Cache Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17' + 'Reader and Data Access': '/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349' + 'Resource Policy Contributor': '/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608' + 'Scheduler Job Collections Contributor': '/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94' + 'Search Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0' + 'Security Admin': '/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd' + 'Security Reader': '/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4' + 'Spatial Anchors Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827' + 'Site Recovery Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567' + 'Site Recovery Operator': '/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca' + 'Spatial Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413' + 'Site Recovery Reader': '/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149' + 'Spatial Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c' + 'SQL Managed Instance Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d' + 'SQL DB Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec' + 'SQL Security Manager': '/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3' + 'Storage Account Contributor': '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + 'SQL Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437' + 'Storage Account Key Operator Service Role': '/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12' + 'Storage Blob Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe' + 'Storage Blob Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + 'Storage Blob Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' + 'Storage Queue Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88' + 'Storage Queue Data Message Processor': '/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed' + 'Storage Queue Data Message Sender': '/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a' + 'Storage Queue Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925' + 'Support Request Contributor': '/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e' + 'Traffic Manager Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7' + 'Virtual Machine Administrator Login': '/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Virtual Machine User Login': '/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52' + 'Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c' + 'Web Plan Contributor': '/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b' + 'Website Contributor': '/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772' + 'Azure Service Bus Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419' + 'Azure Event Hubs Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec' + 'Attestation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e' + 'HDInsight Cluster Operator': '/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a' + 'Cosmos DB Operator': '/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa' + 'Hybrid Server Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624' + 'Hybrid Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb' + 'Azure Event Hubs Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde' + 'Azure Event Hubs Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975' + 'Azure Service Bus Data Receiver': '/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0' + 'Azure Service Bus Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39' + 'Storage File Data SMB Share Reader': '/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314' + 'Storage File Data SMB Share Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb' + 'Private DNS Zone Contributor': '/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f' + 'Storage Blob Delegator': '/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Storage File Data SMB Share Elevated Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7' + 'Blueprint Contributor': '/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4' + 'Blueprint Operator': '/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090' + 'Azure Sentinel Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade' + 'Azure Sentinel Responder': '/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056' + 'Azure Sentinel Reader': '/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb' + 'Workbook Reader': '/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d' + 'Workbook Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad' + 'SignalR AccessKey Reader': '/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e' + 'SignalR/Web PubSub Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761' + 'Azure Connected Machine Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' + 'Azure Connected Machine Resource Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302' + 'Managed Services Registration assignment Delete Role': '/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46' + 'App Configuration Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b' + 'App Configuration Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071' + 'Kubernetes Cluster - Azure Arc Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41' + 'Experimentation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c' + 'Cognitive Services QnA Maker Reader': '/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126' + 'Cognitive Services QnA Maker Editor': '/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025' + 'Experimentation Administrator': '/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c' + 'Remote Rendering Administrator': '/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e' + 'Remote Rendering Client': '/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Security Assessment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5' + 'Tag Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f' + 'Integration Service Environment Developer': '/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec' + 'Integration Service Environment Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8' + 'Azure Kubernetes Service Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8' + 'Azure Digital Twins Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3' + 'Azure Digital Twins Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe' + 'Hierarchy Settings Administrator': '/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d' + 'FHIR Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd' + 'FHIR Data Exporter': '/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843' + 'FHIR Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508' + 'FHIR Data Writer': '/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913' + 'Experimentation Reader': '/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1' + 'Object Understanding Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745' + 'Azure Maps Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204' + 'Cognitive Services Custom Vision Contributor': '/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + 'Cognitive Services Custom Vision Deployment': '/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f' + 'Cognitive Services Custom Vision Labeler': '/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c' + 'Cognitive Services Custom Vision Reader': '/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73' + 'Cognitive Services Custom Vision Trainer': '/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + 'Key Vault Administrator': '/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483' + 'Key Vault Crypto Officer': '/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603' + 'Key Vault Crypto User': '/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424' + 'Key Vault Secrets Officer': '/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7' + 'Key Vault Secrets User': '/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6' + 'Key Vault Certificates Officer': '/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985' + 'Key Vault Reader': '/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2' + 'Key Vault Crypto Service Encryption User': '/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6' + 'Azure Arc Kubernetes Viewer': '/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4' + 'Azure Arc Kubernetes Writer': '/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1' + 'Azure Arc Kubernetes Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2' + 'Azure Arc Kubernetes Admin': '/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96' + 'Azure Kubernetes Service RBAC Cluster Admin': '/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b' + 'Azure Kubernetes Service RBAC Admin': '/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7' + 'Azure Kubernetes Service RBAC Reader': '/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db' + 'Azure Kubernetes Service RBAC Writer': '/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb' + 'Services Hub Operator': '/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b' + 'Object Understanding Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6' + 'Azure Arc Enabled Kubernetes Cluster User Role': '/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd' + 'SignalR REST API Owner': '/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521' + 'Collaborative Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352' + 'Device Update Reader': '/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f' + 'Device Update Administrator': '/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a' + 'Device Update Content Administrator': '/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98' + 'Device Update Deployments Administrator': '/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432' + 'Device Update Deployments Reader': '/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f' + 'Device Update Content Reader': '/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b' + 'Cognitive Services Metrics Advisor Administrator': '/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a' + 'Cognitive Services Metrics Advisor User': '/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8' + 'AgFood Platform Service Reader': '/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba' + 'AgFood Platform Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728' + 'AgFood Platform Service Admin': '/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3' + 'Managed HSM contributor': '/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d' + 'Security Detonation Chamber Submitter': '/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0' + 'SignalR REST API Reader': '/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035' + 'SignalR Service Owner': '/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3' + 'Reservation Purchaser': '/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689' + 'Storage Account Backup Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1' + 'Experimentation Metric Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0' + 'Project Babylon Data Curator': '/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889' + 'Project Babylon Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446' + 'Project Babylon Data Source Administrator': '/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Disk Backup Reader': '/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' + 'Disk Restore Operator': '/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13' + 'Disk Snapshot Contributor': '/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce' + 'Microsoft.Kubernetes connected cluster role': '/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f' + 'Security Detonation Chamber Submission Manager': '/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce' + 'Security Detonation Chamber Publisher': '/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500' + 'Collaborative Runtime Operator': '/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102' + 'CosmosRestoreOperator': '/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f' + 'FHIR Data Converter': '/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24' + 'Azure Sentinel Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a' + 'Quota Request Operator': '/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125' + 'EventGrid Contributor': '/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de' + 'Security Detonation Chamber Reader': '/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5' + 'Object Anchors Account Reader': '/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9' + 'Object Anchors Account Owner': '/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b' + 'WorkloadBuilder Migration Agent Role': '/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c' + 'Azure Spring Cloud Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c' + 'Cognitive Services Speech User': '/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447' + 'Cognitive Services Speech Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181' + 'Cognitive Services Face Recognizer': '/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7' + 'Media Services Account Administrator': '/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466' + 'Media Services Live Events Administrator': '/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77' + 'Media Services Media Operator': '/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c' + 'Media Services Policy Administrator': '/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae' + 'Media Services Streaming Endpoints Administrator': '/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804' + 'Stream Analytics Query Tester': '/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf' + 'AnyBuild Builder': '/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8' + 'IoT Hub Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3' + 'IoT Hub Twin Contributor': '/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c' + 'IoT Hub Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47' + 'IoT Hub Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f' + 'Test Base Reader': '/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85' + 'Search Index Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f' + 'Search Index Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7' + 'Storage Table Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6' + 'Storage Table Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + 'DICOM Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a' + 'DICOM Data Owner': '/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8' + 'EventGrid Data Sender': '/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7' + 'Disk Pool Operator': '/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840' + 'AzureML Data Scientist': '/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121' + 'Grafana Admin': '/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41' + 'Azure Connected SQL Server Onboarding': '/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508' + 'Azure Relay Sender': '/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d' + 'Azure Relay Owner': '/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38' + 'Azure Relay Listener': '/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d' + 'Grafana Viewer': '/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769' + 'Grafana Editor': '/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f' + 'Automation Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867' + 'Kubernetes Extension Contributor': '/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717' + 'Device Provisioning Service Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8' + 'Device Provisioning Service Data Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633' + 'CodeSigning Certificate Profile Signer': '/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958' + 'Azure Spring Cloud Service Registry Reader': '/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65' + 'Azure Spring Cloud Service Registry Contributor': '/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1' + 'Azure Spring Cloud Config Server Reader': '/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7' + 'Azure Spring Cloud Config Server Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b' + 'Azure VM Managed identities restore Contributor': '/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd' + 'Azure Maps Search and Render Data Reader': '/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005' + 'Azure Maps Contributor': '/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb' +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { + name: guid(subscriptionId, roleDefinitionId_var, principalId) + properties: { + roleDefinitionId: roleDefinitionId_var + principalId: principalId + description: !empty(description) ? description : null + principalType: !empty(principalType) ? any(principalType) : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + condition: !empty(condition) ? condition : null + } +} + +@sys.description('The GUID of the Role Assignment') +output name string = roleAssignment.name + +@sys.description('The resource ID of the Role Assignment') +output scope string = subscription().id + +@sys.description('The scope this Role Assignment applies to') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/roleAssignments', roleAssignment.name) diff --git a/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/readme.md b/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/readme.md new file mode 100644 index 000000000..a9f6fa476 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/readme.md @@ -0,0 +1,49 @@ +# Role Assignment on Subscription level `[Microsoft.Authorization/roleAssignments/subscription]` + +With this module you can perform role assignments on a subscription level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `principalId` | string | The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `roleDefinitionIdOrName` | string | 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' | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | `''` | | The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `'2.0'` | `[2.0]` | Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | `''` | | ID of the delegated managed identity resource | +| `description` | string | `''` | | Description of role assignment | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location deployment metadata. | +| `principalType` | string | `''` | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | The principal type of the assigned principal ID. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | 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/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/version.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleAssignments/version.json b/carml/1.2.0/Microsoft.Authorization/roleAssignments/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleAssignments/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 000000000..c4a88ba9e --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json new file mode 100644 index 000000000..d49ce1cae --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json new file mode 100644 index 000000000..cf6825cc0 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json new file mode 100644 index 000000000..c27ff2f86 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json new file mode 100644 index 000000000..87bbbc20b --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.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": { + "roleName": { + "value": "<>-az-testRole-sub-min" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json new file mode 100644 index 000000000..62e03ca98 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/.parameters/sub.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-sub" + }, + "description": { + "value": "Test Custom Role Definition Standard (subscription 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/<>" + ] + }, + "subscriptionId": { + "value": "<>" + } + } +} diff --git a/carml/1.2.0/Microsoft.Authorization/roleDefinitions/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/deploy.bicep new file mode 100644 index 000000000..ccaba2cd6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/deploy.bicep @@ -0,0 +1,108 @@ +targetScope = 'managementGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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 = '' + +@sys.description('Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to.') +param resourceGroupName string = '' + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Role definition assignable scopes. If not provided, will use the current scope provided.') +param assignableScopes array = [] + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module roleDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-MG-Module' + scope: managementGroup(managementGroupId) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + managementGroupId: managementGroupId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module roleDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-Sub-Module' + scope: subscription(subscriptionId) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + dataActions: !empty(dataActions) ? dataActions : [] + notDataActions: !empty(notDataActions) ? notDataActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + subscriptionId: subscriptionId + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module roleDefinition_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${uniqueString(deployment().name, location)}-RoleDefinition-RG-Module' + scope: resourceGroup(subscriptionId, resourceGroupName) + params: { + roleName: roleName + description: !empty(description) ? description : '' + actions: !empty(actions) ? actions : [] + notActions: !empty(notActions) ? notActions : [] + dataActions: !empty(dataActions) ? dataActions : [] + notDataActions: !empty(notDataActions) ? notDataActions : [] + assignableScopes: !empty(assignableScopes) ? assignableScopes : [] + subscriptionId: subscriptionId + resourceGroupName: resourceGroupName + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@sys.description('The GUID of the Role Definition') +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(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(subscriptionId) && empty(resourceGroupName) ? roleDefinition_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_sub.outputs.scope : roleDefinition_rg.outputs.scope) diff --git a/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep new file mode 100644 index 000000000..1b1bafe1e --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep @@ -0,0 +1,63 @@ +targetScope = 'managementGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@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 = [] + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, managementGroupId) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + } + ] + assignableScopes: assignableScopes == [] ? array(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId)) : assignableScopes + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +output scope string = tenantResourceId('Microsoft.Management/managementGroups', managementGroupId) + +@sys.description('The resource ID of the Role Definition') +output resourceId string = extensionResourceId(tenantResourceId('Microsoft.Management/managementGroups', managementGroupId), 'Microsoft.Authorization/roleDefinitions', roleDefinition.name) diff --git a/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md new file mode 100644 index 000000000..0969defa3 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md @@ -0,0 +1,47 @@ +# Role Definitions on Management Group level `[Microsoft.Authorization/roleDefinitions/managementGroup]` + +With this module you can create role definitions on a management group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | 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 | `[]` | List of denied actions. | + + +## 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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/version.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/managementGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/readme.md b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/readme.md new file mode 100644 index 000000000..818735d01 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/readme.md @@ -0,0 +1,119 @@ +# Role Definitions `[Microsoft.Authorization/roleDefinitions]` + +This module deploys custom RBAC Role Definitions across the management group, subscription or resource group scope. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Module Usage Guidance](#Module-Usage-Guidance) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `managementGroupId` | string | `[managementGroup().name]` | 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 | `[]` | List of denied actions. | +| `notDataActions` | array | `[]` | List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `resourceGroupName` | string | `''` | The name of the Resource Group where the Role Definition and Target Scope will be applied to. | +| `subscriptionId` | string | `''` | The subscription ID where the Role Definition and Target Scope will be applied to. Use for both Subscription level and Resource Group Level. | + + +### Parameter Usage: `managementGroupId` + +To deploy resource to a Management Group, provide the `managementGroupId` as an input parameter to the module. + +```json +"managementGroupId": { + "value": "contoso-group" +} +``` + +> `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` + +To deploy resource to an Azure Subscription, provide the `subscriptionId` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +} +``` + +### Parameter Usage: `resourceGroupName` + +To deploy resource to a Resource Group, provide the `subscriptionId` and `resourceGroupName` as an input parameter to the module. **Example**: + +```json +"subscriptionId": { + "value": "12345678-b049-471c-95af-123456789012" +}, +"resourceGroupName": { + "value": "target-resourceGroup" +} +``` + +> 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 | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Definition | +| `resourceId` | string | The resource ID of the Role Definition | +| `roleDefinitionScope` | string | The scope this Role Definition applies to | + +## Considerations + +This module can be deployed both at subscription or resource group level: + +- To deploy the module at resource group level, provide a valid name of an existing Resource Group in the `resourceGroupName` parameter and an existing subscription ID in the `subscriptionId` parameter. +- To deploy the module at the subscription level, provide an existing subscription ID in the `subscriptionId` parameter. +- To deploy the module at the management group level, provide an existing management group ID in the `managementGroupId` parameter. + +## Template references + +- [Roledefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2018-01-01-preview/roleDefinitions) diff --git a/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep new file mode 100644 index 000000000..9ba0c6ec4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep @@ -0,0 +1,73 @@ +targetScope = 'resourceGroup' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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. 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. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, subscriptionId, resourceGroupName) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + dataActions: dataActions + notDataActions: notDataActions + } + ] + assignableScopes: assignableScopes == [] ? array(resourceGroup().id) : assignableScopes + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md new file mode 100644 index 000000000..d9c3b75bf --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md @@ -0,0 +1,50 @@ +# Role Definitions on Resource Group level `[Microsoft.Authorization/roleDefinitions/resourceGroup]` + +With this module you can create role definitions on a resource group level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `notActions` | array | `[]` | List of denied actions. | +| `notDataActions` | array | `[]` | List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `resourceGroupName` | string | `[resourceGroup().name]` | 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. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | 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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep new file mode 100644 index 000000000..bb0746034 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep @@ -0,0 +1,71 @@ +targetScope = 'subscription' + +@sys.description('Required. Name of the custom RBAC role to be created.') +param roleName string + +@sys.description('Optional. Description of the custom RBAC role to be created.') +param description string = '' + +@sys.description('Optional. List of allowed actions.') +param actions array = [] + +@sys.description('Optional. List of denied actions.') +param notActions array = [] + +@sys.description('Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes') +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. 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.') +param assignableScopes array = [] + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { + name: guid(roleName, subscriptionId) + properties: { + roleName: roleName + description: description + type: 'customRole' + permissions: [ + { + actions: actions + notActions: notActions + dataActions: dataActions + notDataActions: notDataActions + } + ] + assignableScopes: !empty(assignableScopes) ? assignableScopes : array(subscription().id) + } +} + +@sys.description('The GUID of the Role Definition') +output name string = roleDefinition.name + +@sys.description('The scope this Role Definition applies to') +output scope string = subscription().id + +@sys.description('The resource ID of the Role Definition') +output resourceId string = subscriptionResourceId(subscriptionId, 'Microsoft.Authorization/roleDefinitions', roleDefinition.name) diff --git a/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/readme.md b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/readme.md new file mode 100644 index 000000000..694f9f6d5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/readme.md @@ -0,0 +1,49 @@ +# Role Definitions on Subscription level `[Microsoft.Authorization/roleDefinitions/subscription]` + +With this module you can create role definitions on a subscription level + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `roleName` | string | Name of the custom RBAC role to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | List of allowed actions. | +| `assignableScopes` | array | `[]` | Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | `''` | Description of the custom RBAC role to be created. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `notActions` | array | `[]` | List of denied actions. | +| `notDataActions` | array | `[]` | List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `subscriptionId` | string | `[subscription().subscriptionId]` | 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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/version.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/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/carml/1.2.0/Microsoft.Authorization/roleDefinitions/version.json b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Authorization/roleDefinitions/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/carml/1.2.0/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ad9e1c7ba --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/availabilitySets/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource availabilitySet 'Microsoft.Compute/availabilitySets@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(availabilitySet.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: availabilitySet +}] diff --git a/carml/1.2.0/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json new file mode 100644 index 000000000..99d2414f7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/availabilitySets/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avs-min-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/availabilitySets/.parameters/parameters.json b/carml/1.2.0/Microsoft.Compute/availabilitySets/.parameters/parameters.json new file mode 100644 index 000000000..cfa2eab50 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/availabilitySets/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avs-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "proximityPlacementGroupId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/proximityPlacementGroups/adp-<>-az-ppg-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/availabilitySets/deploy.bicep b/carml/1.2.0/Microsoft.Compute/availabilitySets/deploy.bicep new file mode 100644 index 000000000..89ee09731 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/availabilitySets/deploy.bicep @@ -0,0 +1,94 @@ +@description('Required. The name of the availability set that is being created.') +param name string + +@description('Optional. The number of fault domains to use.') +param availabilitySetFaultDomain int = 2 + +@description('Optional. The number of update domains to use.') +param availabilitySetUpdateDomain int = 5 + +@description('''Optional. SKU of the availability set. +- Use \'Aligned\' for virtual machines with managed disks +- Use \'Classic\' for virtual machines with unmanaged disks. +''') +param availabilitySetSku string = 'Aligned' + +@description('Optional. Resource ID of a proximity placement group.') +param proximityPlacementGroupId string = '' + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource availabilitySet 'Microsoft.Compute/availabilitySets@2021-07-01' = { + name: name + location: location + tags: tags + properties: { + platformFaultDomainCount: availabilitySetFaultDomain + platformUpdateDomainCount: availabilitySetUpdateDomain + proximityPlacementGroup: !empty(proximityPlacementGroupId) ? { + id: proximityPlacementGroupId + } : null + } + sku: { + name: availabilitySetSku + } +} + +resource availabilitySet_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${availabilitySet.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: availabilitySet +} + +module availabilitySet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AvSet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: availabilitySet.id + } +}] + +@description('The name of the availability set') +output name string = availabilitySet.name + +@description('The resource ID of the availability set') +output resourceId string = availabilitySet.id + +@description('The resource group the availability set was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Compute/availabilitySets/readme.md b/carml/1.2.0/Microsoft.Compute/availabilitySets/readme.md new file mode 100644 index 000000000..b4b14af26 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/availabilitySets/readme.md @@ -0,0 +1,96 @@ +# Availability Sets `[Microsoft.Compute/availabilitySets]` + +This template deploys an availability set + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/availabilitySets` | 2021-07-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the availability set that is being created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `availabilitySetFaultDomain` | int | `2` | | The number of fault domains to use. | +| `availabilitySetSku` | string | `'Aligned'` | | SKU of the availability set.

    - Use \'Aligned\' for virtual machines with managed disks

    - Use \'Classic\' for virtual machines with unmanaged disks.

    | +| `availabilitySetUpdateDomain` | int | `5` | | The number of update domains to use. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `proximityPlacementGroupId` | string | `''` | | Resource ID of a proximity placement group. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the availability set resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the availability set | +| `resourceGroupName` | string | The resource group the availability set was deployed into | +| `resourceId` | string | The resource ID of the availability set | + +## Template references + +- [Availabilitysets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/availabilitySets) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Compute/availabilitySets/version.json b/carml/1.2.0/Microsoft.Compute/availabilitySets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/availabilitySets/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/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep new file mode 100644 index 000000000..64765196a --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep @@ -0,0 +1,36 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. The access policy name') +param name string = 'add' + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the access policies assignment') +output name string = policies.name + +@description('The resource ID of the access policies assignment') +output resourceId string = policies.id diff --git a/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ba4152534 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2020-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(diskEncryptionSet.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: diskEncryptionSet +}] diff --git a/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json new file mode 100644 index 000000000..9ad9ed7c5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-des-x-001" + }, + "keyVaultId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "keyUrl": { + "value": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5" // ID must be updated for new keys + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/deploy.bicep b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/deploy.bicep new file mode 100644 index 000000000..6be6e1972 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/deploy.bicep @@ -0,0 +1,111 @@ +@description('Required. The name of the disk encryption set that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@description('Required. Resource ID of the KeyVault containing the key or secret.') +param keyVaultId string + +@description('Required. Key URL (with version) pointing to a key or secret in KeyVault.') +param keyUrl string + +@description('Optional. The type of key used to encrypt the data of the disk. For security reasons, it is recommended to set encryptionType to EncryptionAtRestWithPlatformAndCustomerKeys') +@allowed([ + 'EncryptionAtRestWithCustomerKey' + 'EncryptionAtRestWithPlatformAndCustomerKeys' +]) +param encryptionType string = 'EncryptionAtRestWithPlatformAndCustomerKeys' + +@description('Optional. Set this flag to true to enable auto-updating of this disk encryption set to the latest key version.') +param rotationToLatestKeyVersionEnabled bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the disk encryption resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + activeKey: { + sourceVault: { + id: keyVaultId + } + keyUrl: keyUrl + } + encryptionType: encryptionType + rotationToLatestKeyVersionEnabled: rotationToLatestKeyVersionEnabled + } +} + +module keyVaultAccessPolicies '.bicep/nested_kvAccessPolicy.bicep' = { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-KVAccessPolicies' + params: { + keyVaultName: last(split(keyVaultId, '/')) + accessPolicies: [ + { + tenantId: subscription().tenantId + objectId: diskEncryptionSet.identity.principalId + permissions: { + keys: [ + 'get' + 'wrapKey' + 'unwrapKey' + ] + secrets: [] + certificates: [] + } + } + ] + } + // This is to support access policies to KV in different subscription and resource group than the disk encryption set. + scope: resourceGroup(split(keyVaultId, '/')[2], split(keyVaultId, '/')[4]) +} + +module diskEncryptionSet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: diskEncryptionSet.id + } +}] + +@description('The resource ID of the disk encryption set') +output resourceId string = diskEncryptionSet.id + +@description('The name of the disk encryption set') +output name string = diskEncryptionSet.name + +@description('The resource group the disk encryption set was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the disk encryption set') +output systemAssignedPrincipalId string = diskEncryptionSet.identity.principalId + +@description('The name of the key vault with the disk encryption key') +output keyVaultName string = last(split(keyVaultId, '/')) diff --git a/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/readme.md b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/readme.md new file mode 100644 index 000000000..a5c33b0f1 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/readme.md @@ -0,0 +1,97 @@ +# Disk Encryption Sets `[Microsoft.Compute/diskEncryptionSets]` + +This template deploys a disk encryption set. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/diskEncryptionSets` | 2021-04-01 | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyUrl` | string | Key URL (with version) pointing to a key or secret in KeyVault. | +| `keyVaultId` | string | Resource ID of the KeyVault containing the key or secret. | +| `name` | string | The name of the disk encryption set that is being created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `encryptionType` | string | `'EncryptionAtRestWithPlatformAndCustomerKeys'` | `[EncryptionAtRestWithCustomerKey, EncryptionAtRestWithPlatformAndCustomerKeys]` | The type of key used to encrypt the data of the disk. For security reasons, it is recommended to set encryptionType to EncryptionAtRestWithPlatformAndCustomerKeys | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `rotationToLatestKeyVersionEnabled` | bool | `False` | | Set this flag to true to enable auto-updating of this disk encryption set to the latest key version. | +| `tags` | object | `{object}` | | Tags of the disk encryption resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault with the disk encryption key | +| `name` | string | The name of the disk encryption set | +| `resourceGroupName` | string | The resource group the disk encryption set was deployed into | +| `resourceId` | string | The resource ID of the disk encryption set | +| `systemAssignedPrincipalId` | string | The principal ID of the disk encryption set | + +## Template references + +- [Diskencryptionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/diskEncryptionSets) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/version.json b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/diskEncryptionSets/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/carml/1.2.0/Microsoft.Compute/disks/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/disks/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..27a1374a5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource disk 'Microsoft.Compute/disks@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(disk.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: disk +}] diff --git a/carml/1.2.0/Microsoft.Compute/disks/.parameters/image.parameters.json b/carml/1.2.0/Microsoft.Compute/disks/.parameters/image.parameters.json new file mode 100644 index 000000000..d6934ac64 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/.parameters/image.parameters.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-image-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "createOption": { + "value": "FromImage" + }, + "imageReferenceId": { + "value": "/Subscriptions/<>/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2016-Datacenter/Versions/14393.4906.2112080838" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/disks/.parameters/import.parameters.json b/carml/1.2.0/Microsoft.Compute/disks/.parameters/import.parameters.json new file mode 100644 index 000000000..a09908e11 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/.parameters/import.parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-import-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "createOption": { + "value": "Import" + }, + "sourceUri": { + "value": "https://adp<>azsax001.blob.core.windows.net/vhds/adp-<>-az-imgt-x-001.vhd" + }, + "storageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/disks/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Compute/disks/.parameters/min.parameters.json new file mode 100644 index 000000000..d19f33a37 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/.parameters/min.parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-min-001" + }, + "sku": { + "value": "Standard_LRS" + }, + "diskSizeGB": { + "value": 1 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/disks/.parameters/parameters.json b/carml/1.2.0/Microsoft.Compute/disks/.parameters/parameters.json new file mode 100644 index 000000000..3608893d9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-disk-x-001" + }, + "sku": { + "value": "UltraSSD_LRS" + }, + "diskSizeGB": { + "value": 128 + }, + "logicalSectorSize": { + "value": 512 + }, + "diskIOPSReadWrite": { + "value": 500 + }, + "diskMBpsReadWrite": { + "value": 60 + }, + "osType": { + "value": "Windows" + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/disks/deploy.bicep b/carml/1.2.0/Microsoft.Compute/disks/deploy.bicep new file mode 100644 index 000000000..463e0069d --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. The name of the disk that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'Standard_LRS' + 'Premium_LRS' + 'StandardSSD_LRS' + 'UltraSSD_LRS' + 'Premium_ZRS' + 'Premium_ZRS' +]) +@description('Required. The disks sku name. Can be .') +param sku string + +@description('Optional. Set to true to enable bursting beyond the provisioned performance target of the disk.') +param burstingEnabled bool = false + +@description('Optional. Percentage complete for the background copy when a resource is created via the CopyStart operation.') +param completionPercent int = 100 + +@allowed([ + 'Attach' + 'Copy' + 'CopyStart' + 'Empty' + 'FromImage' + 'Import' + 'ImportSecure' + 'Restore' + 'Upload' + 'UploadPreparedSecure' +]) +@description('Optional. Sources of a disk creation.') +param createOption string = 'Empty' + +@description('Optional. A relative uri containing either a Platform Image Repository or user image reference.') +param imageReferenceId string = '' + +@description('Optional. Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096.') +param logicalSectorSize int = 4096 + +@description('Optional. If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state.') +param securityDataUri string = '' + +@description('Optional. If create option is Copy, this is the ARM id of the source snapshot or disk.') +param sourceResourceId string = '' + +@description('Optional. If create option is Import, this is the URI of a blob to be imported into a managed disk.') +param sourceUri string = '' + +@description('Optional. Required if create option is Import. The Azure Resource Manager identifier of the storage account containing the blob to import as a disk') +param storageAccountId string = '' + +@description('Optional. If create option is Upload, this is the size of the contents of the upload including the VHD footer.') +param uploadSizeBytes int = 20972032 + +@description('Optional. If create option is empty, this field is mandatory and it indicates the size of the disk to create.') +param diskSizeGB int = 0 + +@description('Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks.') +param diskIOPSReadWrite int = 0 + +@description('Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks.') +param diskMBpsReadWrite int = 0 + +@allowed([ + 'V1' + 'V2' +]) +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only.') +param hyperVGeneration string = 'V2' + +@description('Optional. The maximum number of VMs that can attach to the disk at the same time. Default value is 0.') +param maxShares int = 1 + +@allowed([ + 'AllowAll' + 'AllowPrivate' + 'DenyAll' +]) +@description('Optional. Policy for accessing the disk via network.') +param networkAccessPolicy string = 'DenyAll' + +@allowed([ + 'Windows' + 'Linux' + '' +]) +@description('Optional. Sources of a disk creation.') +param osType string = '' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Policy for controlling export on the disk.') +param publicNetworkAccess string = 'Disabled' + +@description('Optional. True if the image from which the OS disk is created supports accelerated networking.') +param acceleratedNetwork bool = false + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the availability set resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource disk 'Microsoft.Compute/disks@2021-08-01' = { + name: name + location: location + tags: tags + sku: { + name: sku + } + properties: { + burstingEnabled: burstingEnabled + completionPercent: completionPercent + creationData: { + createOption: createOption + imageReference: createOption != 'FromImage' ? null : { + id: imageReferenceId + } + logicalSectorSize: contains(sku, 'Ultra') ? logicalSectorSize : null + securityDataUri: createOption == 'ImportSecure' ? securityDataUri : null + sourceResourceId: createOption == 'Copy' ? sourceResourceId : null + sourceUri: createOption == 'Import' ? sourceUri : null + storageAccountId: createOption == 'Import' ? storageAccountId : null + uploadSizeBytes: createOption == 'Upload' ? uploadSizeBytes : null + } + diskIOPSReadWrite: contains(sku, 'Ultra') ? diskIOPSReadWrite : null + diskMBpsReadWrite: contains(sku, 'Ultra') ? diskMBpsReadWrite : null + diskSizeGB: createOption == 'Empty' ? diskSizeGB : null + hyperVGeneration: empty(osType) ? null : hyperVGeneration + maxShares: maxShares + networkAccessPolicy: networkAccessPolicy + osType: empty(osType) ? null : osType + publicNetworkAccess: publicNetworkAccess + supportedCapabilities: empty(osType) ? {} : { + acceleratedNetwork: acceleratedNetwork + } + } +} + +resource disk_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${disk.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: disk +} + +module disk_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AvSet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: disk.id + } +}] + +@description('The resource group the disk was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the disk') +output resourceId string = disk.id + +@description('The name of the disk') +output name string = disk.name diff --git a/carml/1.2.0/Microsoft.Compute/disks/readme.md b/carml/1.2.0/Microsoft.Compute/disks/readme.md new file mode 100644 index 000000000..464b7845f --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/readme.md @@ -0,0 +1,112 @@ +# Compute Disks `[Microsoft.Compute/disks]` + +This template deploys a disk + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/disks` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | | The name of the disk that is being created. | +| `sku` | string | `[Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS, Premium_ZRS, Premium_ZRS]` | The disks sku name. Can be . | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `acceleratedNetwork` | bool | `False` | | True if the image from which the OS disk is created supports accelerated networking. | +| `burstingEnabled` | bool | `False` | | Set to true to enable bursting beyond the provisioned performance target of the disk. | +| `completionPercent` | int | `100` | | Percentage complete for the background copy when a resource is created via the CopyStart operation. | +| `createOption` | string | `'Empty'` | `[Attach, Copy, CopyStart, Empty, FromImage, Import, ImportSecure, Restore, Upload, UploadPreparedSecure]` | Sources of a disk creation. | +| `diskIOPSReadWrite` | int | `0` | | The number of IOPS allowed for this disk; only settable for UltraSSD disks. | +| `diskMBpsReadWrite` | int | `0` | | The bandwidth allowed for this disk; only settable for UltraSSD disks. | +| `diskSizeGB` | int | `0` | | If create option is empty, this field is mandatory and it indicates the size of the disk to create. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hyperVGeneration` | string | `'V2'` | `[V1, V2]` | The hypervisor generation of the Virtual Machine. Applicable to OS disks only. | +| `imageReferenceId` | string | `''` | | A relative uri containing either a Platform Image Repository or user image reference. | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `logicalSectorSize` | int | `4096` | | Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096. | +| `maxShares` | int | `1` | | The maximum number of VMs that can attach to the disk at the same time. Default value is 0. | +| `networkAccessPolicy` | string | `'DenyAll'` | `[AllowAll, AllowPrivate, DenyAll]` | Policy for accessing the disk via network. | +| `osType` | string | `''` | `[Windows, Linux, ]` | Sources of a disk creation. | +| `publicNetworkAccess` | string | `'Disabled'` | `[Disabled, Enabled]` | Policy for controlling export on the disk. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityDataUri` | string | `''` | | If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state. | +| `sourceResourceId` | string | `''` | | If create option is Copy, this is the ARM id of the source snapshot or disk. | +| `sourceUri` | string | `''` | | If create option is Import, this is the URI of a blob to be imported into a managed disk. | +| `storageAccountId` | string | `''` | | Required if create option is Import. The Azure Resource Manager identifier of the storage account containing the blob to import as a disk | +| `tags` | object | `{object}` | | Tags of the availability set resource. | +| `uploadSizeBytes` | int | `20972032` | | If create option is Upload, this is the size of the contents of the upload including the VHD footer. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the disk | +| `resourceGroupName` | string | The resource group the disk was deployed into | +| `resourceId` | string | The resource ID of the disk | + +## Template references + +- [Disks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-08-01/disks) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Compute/disks/version.json b/carml/1.2.0/Microsoft.Compute/disks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/disks/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/carml/1.2.0/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..1a5646659 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(gallery.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: gallery +}] diff --git a/carml/1.2.0/Microsoft.Compute/galleries/.parameters/images.parameters.json b/carml/1.2.0/Microsoft.Compute/galleries/.parameters/images.parameters.json new file mode 100644 index 000000000..78a802c19 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/.parameters/images.parameters.json @@ -0,0 +1,50 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsigweuimages001" + }, + "images": { + "value": [ + { + "name": "<>-az-imgd-x-003" + }, + { + "name": "<>-az-imgd-x-001", + "osType": "Windows", + "osState": "Generalized", + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2022-datacenter-azure-edition", + "minRecommendedvCPUs": 2, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "maxRecommendedMemory": 16, + "hyperVGeneration": "V1", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "<>-az-imgd-x-002", + "osType": "Linux", + "osState": "Generalized", + "publisher": "canonical", + "offer": "0001-com-ubuntu-server-focal", + "sku": "20_04-lts-gen2", + "minRecommendedvCPUs": 1, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "maxRecommendedMemory": 32, + "hyperVGeneration": "V2" + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/galleries/.parameters/parameters.json b/carml/1.2.0/Microsoft.Compute/galleries/.parameters/parameters.json new file mode 100644 index 000000000..ccacaf074 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsigweux001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/galleries/deploy.bicep b/carml/1.2.0/Microsoft.Compute/galleries/deploy.bicep new file mode 100644 index 000000000..621c3f9ba --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/deploy.bicep @@ -0,0 +1,111 @@ +@minLength(1) +@description('Required. Name of the Azure Shared Image Gallery') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Description of the Azure Shared Image Gallery') +param galleryDescription string = '' + +@description('Optional. Images to create') +param images array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for all resources.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' = { + name: name + location: location + tags: tags + properties: { + description: galleryDescription + identifier: {} + } +} + +resource gallery_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${gallery.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: gallery +} + +module gallery_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Gallery-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: gallery.id + } +}] + +// Images +module galleries_images 'images/deploy.bicep' = [for (image, index) in images: { + name: '${uniqueString(deployment().name, location)}-Gallery-Image-${index}' + params: { + name: image.name + galleryName: gallery.name + osType: contains(image, 'osType') ? image.osType : 'Windows' + osState: contains(image, 'osState') ? image.osState : 'Generalized' + publisher: contains(image, 'publisher') ? image.publisher : 'MicrosoftWindowsServer' + offer: contains(image, 'offer') ? image.offer : 'WindowsServer' + sku: contains(image, 'sku') ? image.sku : '2019-Datacenter' + minRecommendedvCPUs: contains(image, 'minRecommendedvCPUs') ? image.minRecommendedvCPUs : 1 + maxRecommendedvCPUs: contains(image, 'maxRecommendedvCPUs') ? image.maxRecommendedvCPUs : 4 + minRecommendedMemory: contains(image, 'minRecommendedMemory') ? image.minRecommendedMemory : 4 + maxRecommendedMemory: contains(image, 'maxRecommendedMemory') ? image.maxRecommendedMemory : 16 + hyperVGeneration: contains(image, 'hyperVGeneration') ? image.hyperVGeneration : 'V1' + imageDefinitionDescription: contains(image, 'imageDefinitionDescription') ? image.imageDefinitionDescription : '' + eula: contains(image, 'eula') ? image.eula : '' + privacyStatementUri: contains(image, 'privacyStatementUri') ? image.privacyStatementUri : '' + releaseNoteUri: contains(image, 'releaseNoteUri') ? image.releaseNoteUri : '' + productName: contains(image, 'productName') ? image.productName : '' + planName: contains(image, 'planName') ? image.planName : '' + planPublisherName: contains(image, 'planPublisherName') ? image.planPublisherName : '' + endOfLife: contains(image, 'endOfLife') ? image.endOfLife : '' + excludedDiskTypes: contains(image, 'excludedDiskTypes') ? image.excludedDiskTypes : [] + roleAssignments: contains(image, 'roleAssignments') ? image.roleAssignments : [] + tags: contains(image, 'tags') ? image.tags : {} + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The resource ID of the deployed image gallery') +output resourceId string = gallery.id + +@description('The resource group of the deployed image gallery') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployed image gallery') +output name string = gallery.name diff --git a/carml/1.2.0/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..927fe6d86 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/images/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'myCustomRoleAtSub': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3') +} + +resource galleryImage 'Microsoft.Compute/galleries/images@2020-09-30' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(galleryImage.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: galleryImage +}] diff --git a/carml/1.2.0/Microsoft.Compute/galleries/images/deploy.bicep b/carml/1.2.0/Microsoft.Compute/galleries/images/deploy.bicep new file mode 100644 index 000000000..2de2cd544 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/images/deploy.bicep @@ -0,0 +1,171 @@ +@description('Required. Name of the image definition.') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Name of the Azure Shared Image Gallery') +@minLength(1) +param galleryName string + +@description('Optional. OS type of the image to be created.') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string = 'Windows' + +@description('Optional. This property allows the user to specify whether the virtual machines created under this image are \'Generalized\' or \'Specialized\'.') +@allowed([ + 'Generalized' + 'Specialized' +]) +param osState string = 'Generalized' + +@description('Optional. The name of the gallery Image Definition publisher.') +param publisher string = 'MicrosoftWindowsServer' + +@description('Optional. The name of the gallery Image Definition offer.') +param offer string = 'WindowsServer' + +@description('Optional. The name of the gallery Image Definition SKU.') +param sku string = '2019-Datacenter' + +@description('Optional. The minimum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param minRecommendedvCPUs int = 1 + +@description('Optional. The maximum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param maxRecommendedvCPUs int = 4 + +@description('Optional. The minimum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param minRecommendedMemory int = 4 + +@description('Optional. The maximum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param maxRecommendedMemory int = 16 + +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2') +@allowed([ + 'V1' + 'V2' +]) +param hyperVGeneration string = 'V1' + +@description('Optional. The description of this gallery Image Definition resource. This property is updatable.') +param imageDefinitionDescription string = '' + +@description('Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL.') +param eula string = '' + +@description('Optional. The privacy statement uri. Has to be a valid URL.') +param privacyStatementUri string = '' + +@description('Optional. The release note uri. Has to be a valid URL.') +param releaseNoteUri string = '' + +@description('Optional. The product ID.') +param productName string = '' + +@description('Optional. The plan ID.') +param planName string = '' + +@description('Optional. The publisher ID.') +param planPublisherName string = '' + +@description('Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z') +param endOfLife string = '' + +@description('Optional. List of the excluded disk types. E.g. Standard_LRS') +param excludedDiskTypes array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for all resources.') +param tags object = {} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource gallery 'Microsoft.Compute/galleries@2020-09-30' existing = { + name: galleryName +} + +resource image 'Microsoft.Compute/galleries/images@2020-09-30' = { + name: name + parent: gallery + location: location + tags: tags + properties: { + osType: osType + osState: osState + identifier: { + publisher: publisher + offer: offer + sku: sku + } + recommended: { + vCPUs: { + min: minRecommendedvCPUs + max: maxRecommendedvCPUs + } + memory: { + min: minRecommendedMemory + max: maxRecommendedMemory + } + } + hyperVGeneration: hyperVGeneration + description: imageDefinitionDescription + eula: eula + privacyStatementUri: privacyStatementUri + releaseNoteUri: releaseNoteUri + purchasePlan: { + product: !empty(productName) ? productName : null + name: !empty(planName) ? planName : null + publisher: !empty(planPublisherName) ? planPublisherName : null + } + endOfLifeDate: endOfLife + disallowed: { + diskTypes: excludedDiskTypes + } + } +} + +module galleryImage_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: image.id + } +}] + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the image') +output resourceId string = image.id + +@description('The name of the image') +output name string = image.name diff --git a/carml/1.2.0/Microsoft.Compute/galleries/images/readme.md b/carml/1.2.0/Microsoft.Compute/galleries/images/readme.md new file mode 100644 index 000000000..a5e3c6399 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/images/readme.md @@ -0,0 +1,109 @@ +# Shared Image Definition `[Microsoft.Compute/galleries/images]` + +This module deploys an Image Definition in a Shared Image Gallery. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/galleries/images` | 2020-09-30 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `galleryName` | string | Name of the Azure Shared Image Gallery | +| `name` | string | Name of the image definition. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endOfLife` | string | `''` | | The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z | +| `eula` | string | `''` | | The Eula agreement for the gallery Image Definition. Has to be a valid URL. | +| `excludedDiskTypes` | array | `[]` | | List of the excluded disk types. E.g. Standard_LRS | +| `hyperVGeneration` | string | `'V1'` | `[V1, V2]` | The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2 | +| `imageDefinitionDescription` | string | `''` | | The description of this gallery Image Definition resource. This property is updatable. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `maxRecommendedMemory` | int | `16` | | The maximum amount of RAM in GB recommended for this image. | +| `maxRecommendedvCPUs` | int | `4` | | The maximum number of the CPU cores recommended for this image. | +| `minRecommendedMemory` | int | `4` | | The minimum amount of RAM in GB recommended for this image. | +| `minRecommendedvCPUs` | int | `1` | | The minimum number of the CPU cores recommended for this image. | +| `offer` | string | `'WindowsServer'` | | The name of the gallery Image Definition offer. | +| `osState` | string | `'Generalized'` | `[Generalized, Specialized]` | This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'. | +| `osType` | string | `'Windows'` | `[Windows, Linux]` | OS type of the image to be created. | +| `planName` | string | `''` | | The plan ID. | +| `planPublisherName` | string | `''` | | The publisher ID. | +| `privacyStatementUri` | string | `''` | | The privacy statement uri. Has to be a valid URL. | +| `productName` | string | `''` | | The product ID. | +| `publisher` | string | `'MicrosoftWindowsServer'` | | The name of the gallery Image Definition publisher. | +| `releaseNoteUri` | string | `''` | | The release note uri. Has to be a valid URL. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'2019-Datacenter'` | | The name of the gallery Image Definition SKU. | +| `tags` | object | `{object}` | | Tags for all resources. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image | +| `resourceGroupName` | string | The resource group the image was deployed into | +| `resourceId` | string | The resource ID of the image | + +## Template references + +- [Galleries/Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries/images) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Compute/galleries/images/version.json b/carml/1.2.0/Microsoft.Compute/galleries/images/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/images/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/carml/1.2.0/Microsoft.Compute/galleries/readme.md b/carml/1.2.0/Microsoft.Compute/galleries/readme.md new file mode 100644 index 000000000..4fc1819d1 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/readme.md @@ -0,0 +1,96 @@ +# Azure Compute Galleries `[Microsoft.Compute/galleries]` + +This module deploys an Azure compute gallery (formerly known as shared image gallery). + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/galleries` | 2020-09-30 | +| `Microsoft.Compute/galleries/images` | 2020-09-30 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Shared Image Gallery | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `galleryDescription` | string | `''` | | Description of the Azure Shared Image Gallery | +| `images` | _[images](images/readme.md)_ array | `[]` | | Images to create | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags for all resources. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed image gallery | +| `resourceGroupName` | string | The resource group of the deployed image gallery | +| `resourceId` | string | The resource ID of the deployed image gallery | + +## Template references + +- [Galleries](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries) +- [Galleries/Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-09-30/galleries/images) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Compute/galleries/version.json b/carml/1.2.0/Microsoft.Compute/galleries/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/galleries/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/carml/1.2.0/Microsoft.Compute/images/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/images/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ba00fbee6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/images/.bicep/nested_rbac.bicep @@ -0,0 +1,57 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'myCustomRoleAtSub': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3') +} + +resource image 'Microsoft.Compute/images@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(image.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: image +}] diff --git a/carml/1.2.0/Microsoft.Compute/images/.parameters/parameters.json b/carml/1.2.0/Microsoft.Compute/images/.parameters/parameters.json new file mode 100644 index 000000000..85e8b306e --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/images/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-img-x-001" + }, + "osAccountType": { + "value": "Premium_LRS" + }, + "osType": { + "value": "Windows" + }, + "osDiskBlobUri": { + "value": "https://adp<>azsax001.blob.core.windows.net/vhds/adp-<>-az-imgt-x-001.vhd" + }, + "osDiskCaching": { + "value": "ReadWrite" + }, + "zoneResilient": { + "value": true + }, + "hyperVGeneration": { + "value": "V1" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/images/deploy.bicep b/carml/1.2.0/Microsoft.Compute/images/deploy.bicep new file mode 100644 index 000000000..988bbda55 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/images/deploy.bicep @@ -0,0 +1,83 @@ +@description('Required. The name of the image.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The Virtual Hard Disk.') +param osDiskBlobUri string + +@description('Required. This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux') +param osType string + +@description('Optional. Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite') +param osDiskCaching string + +@description('Optional. Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS') +param osAccountType string + +@description('Optional. Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS).') +param zoneResilient bool = false + +@description('Optional. Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2') +param hyperVGeneration string = 'V1' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource image 'Microsoft.Compute/images@2021-04-01' = { + name: name + location: location + tags: tags + properties: { + storageProfile: { + osDisk: { + osType: osType + blobUri: osDiskBlobUri + caching: osDiskCaching + storageAccountType: osAccountType + } + dataDisks: [] + zoneResilient: zoneResilient + } + hyperVGeneration: hyperVGeneration + } +} + +module image_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Image-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: image.id + } +}] + +@description('The resource ID of the image') +output resourceId string = image.id + +@description('The resource group the image was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image') +output name string = image.name diff --git a/carml/1.2.0/Microsoft.Compute/images/readme.md b/carml/1.2.0/Microsoft.Compute/images/readme.md new file mode 100644 index 000000000..80a46bfbf --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/images/readme.md @@ -0,0 +1,95 @@ +# Images `[Microsoft.Compute/images]` + +This module deploys a compute image. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/images` | 2021-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image. | +| `osDiskBlobUri` | string | The Virtual Hard Disk. | +| `osType` | string | This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hyperVGeneration` | string | `'V1'` | Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2 | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `osAccountType` | string | | Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS | +| `osDiskCaching` | string | | Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | Tags of the resource. | +| `zoneResilient` | bool | `False` | Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS). | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the image | +| `resourceGroupName` | string | The resource group the image was deployed into | +| `resourceId` | string | The resource ID of the image | + +## Template references + +- [Images](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/images) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Compute/images/version.json b/carml/1.2.0/Microsoft.Compute/images/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/images/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/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..0c1d2033e --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(proximityPlacementGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: proximityPlacementGroup +}] diff --git a/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json new file mode 100644 index 000000000..71bff3e25 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ppg-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/deploy.bicep b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/deploy.bicep new file mode 100644 index 000000000..e67aa7740 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/deploy.bicep @@ -0,0 +1,79 @@ +@description('Required. The name of the proximity placement group that is being created.') +param name string = '' + +@description('Optional. Specifies the type of the proximity placement group.') +@allowed([ + 'Standard' + 'Ultra' +]) +param proximityPlacementGroupType string = 'Standard' + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the proximity placement group resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' = { + name: name + location: location + tags: tags + properties: { + proximityPlacementGroupType: proximityPlacementGroupType + } +} + +resource proximityPlacementGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${proximityPlacementGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: proximityPlacementGroup +} + +module proximityPlacementGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ProxPlaceGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: proximityPlacementGroup.id + } +}] + +@description('The name of the proximity placement group') +output name string = proximityPlacementGroup.name + +@description('The resourceId the proximity placement group') +output resourceId string = proximityPlacementGroup.id + +@description('The resource group the proximity placement group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/readme.md b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/readme.md new file mode 100644 index 000000000..4c64d6a1c --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/readme.md @@ -0,0 +1,93 @@ +# Proximity Placement Groups `[Microsoft.Compute/proximityPlacementGroups]` + +This template deploys a proximity placement group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/proximityPlacementGroups` | 2021-04-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | `''` | The name of the proximity placement group that is being created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Resource location. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `proximityPlacementGroupType` | string | `'Standard'` | `[Standard, Ultra]` | Specifies the type of the proximity placement group. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the proximity placement group resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the proximity placement group | +| `resourceGroupName` | string | The resource group the proximity placement group was deployed into | +| `resourceId` | string | The resourceId the proximity placement group | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Proximityplacementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/proximityPlacementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/version.json b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/proximityPlacementGroups/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/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b9c5776a4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2021-04-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(vmss.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: vmss +}] diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json new file mode 100644 index 000000000..0c3f3189b --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.min.parameters.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-linux-min-001" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "skuName": { + "value": "Standard_B2s" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "adminUsername": { + "value": "scaleSetAdmin" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/scaleSetAdmin/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json new file mode 100644 index 000000000..b4d6340af --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/linux.parameters.json @@ -0,0 +1,186 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-linux-001" + }, + "vmNamePrefix": { + "value": "vmsslinvm" + }, + "skuName": { + "value": "Standard_B2s" + }, + "skuCapacity": { + "value": 1 + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmPriority": { + "value": "Regular" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "availabilityZones": { + "value": [ + "2" + ] + }, + "scaleSetFaultDomain": { + "value": 1 + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "bootDiagnosticStorageAccountName": { + "value": "adp<>azsax001" + }, + "osType": { + "value": "Linux" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "adminUsername": { + "value": "scaleSetAdmin" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/scaleSetAdmin/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "dataDisks": { + "value": [ + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "sudo apt-get update" + } + } + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json new file mode 100644 index 000000000..5444ff795 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.min.parameters.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-win-min-001" + }, + "skuName": { + "value": "Standard_B2s" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "adminUsername": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminUsername" + } + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json new file mode 100644 index 000000000..1fec6b76b --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/.parameters/windows.parameters.json @@ -0,0 +1,182 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-scaleset-win-001" + }, + "vmNamePrefix": { + "value": "vmsswinvm" + }, + "skuName": { + "value": "Standard_B2s" + }, + "skuCapacity": { + "value": 1 + }, + "upgradePolicyMode": { + "value": "Manual" + }, + "vmPriority": { + "value": "Regular" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "adminUsername": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminUsername" + } + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-002" + } + } + } + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ], + "protectedSettings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + } + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep new file mode 100644 index 000000000..7930c128f --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/deploy.bicep @@ -0,0 +1,669 @@ +@description('Required. Name of the VMSS.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Fault Domain count for each placement group.') +param scaleSetFaultDomain int = 2 + +@description('Optional. Creates an proximity placement group and adds the VMs to it.') +param proximityPlacementGroupName string = '' + +@description('Optional. Specifies the type of the proximity placement group.') +@allowed([ + 'Standard' + 'Ultra' +]) +param proximityPlacementGroupType string = 'Standard' + +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Specifies the mode of an upgrade to virtual machines in the scale set.\' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling') +@allowed([ + 'Manual' + 'Automatic' + 'Rolling' +]) +param upgradePolicyMode string = 'Manual' + +@description('Optional. The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability.') +param maxBatchInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch') +param maxUnhealthyInstancePercent int = 20 + +@description('Optional. The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch.') +param maxUnhealthyUpgradedInstancePercent int = 20 + +@description('Optional. The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format') +param pauseTimeBetweenBatches string = 'PT0S' + +@description('Optional. Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true.') +param enableAutomaticOSUpgrade bool = false + +@description('Optional. Whether OS image rollback feature should be disabled.') +param disableAutomaticRollback bool = false + +@description('Optional. Specifies whether automatic repairs should be enabled on the virtual machine scale set.') +param automaticRepairsPolicyEnabled bool = false + +@description('Optional. The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M).') +param gracePeriod string = 'PT30M' + +@description('Optional. Specifies the computer name prefix for all of the virtual machines in the scale set.') +@minLength(1) +@maxLength(15) +param vmNamePrefix string = 'vmssvm' + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machines in the scale set.') +param secrets array = [] + +@description('Optional. Specifies Scheduled Event related configurations') +param scheduledEventsProfile object = {} + +@description('Optional. Specifies whether the Virtual Machine Scale Set should be overprovisioned.') +param overprovision bool = false + +@description('Optional. When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs.') +param doNotRunExtensionsOnOverprovisionedVMs bool = false + +@description('Optional. Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage.') +param zoneBalance bool = false + +@description('Optional. When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true.') +param singlePlacementGroup bool = true + +@description('Optional. Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in') +param scaleInPolicy object = { + rules: [ + 'Default' + ] +} + +@description('Required. The SKU size of the VMs.') +param skuName string + +@description('Optional. The initial instance count of scale set VMs.') +param skuCapacity int = 1 + +@description('Optional. The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set.') +param availabilityZones array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param publicIpDiagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2021-04-01' = if (!empty(proximityPlacementGroupName)) { + name: !empty(proximityPlacementGroupName) ? proximityPlacementGroupName : 'dummyProximityGroup' + location: location + tags: tags + properties: { + proximityPlacementGroupType: proximityPlacementGroupType + } +} + +resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: identity + zones: availabilityZones + properties: { + proximityPlacementGroup: !empty(proximityPlacementGroupName) ? { + id: az.resourceId('Microsoft.Compute/proximityPlacementGroups', proximityPlacementGroup.name) + } : null + upgradePolicy: { + mode: upgradePolicyMode + rollingUpgradePolicy: { + maxBatchInstancePercent: maxBatchInstancePercent + maxUnhealthyInstancePercent: maxUnhealthyInstancePercent + maxUnhealthyUpgradedInstancePercent: maxUnhealthyUpgradedInstancePercent + pauseTimeBetweenBatches: pauseTimeBetweenBatches + } + automaticOSUpgradePolicy: { + enableAutomaticOSUpgrade: enableAutomaticOSUpgrade + disableAutomaticRollback: disableAutomaticRollback + } + } + automaticRepairsPolicy: { + enabled: automaticRepairsPolicyEnabled + gracePeriod: gracePeriod + } + virtualMachineProfile: { + osProfile: { + computerNamePrefix: vmNamePrefix + adminUsername: adminUsername + adminPassword: !empty(adminPassword) ? adminPassword : null + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: secrets + } + securityProfile: { + encryptionAtHost: encryptionAtHost + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + createOption: osDisk.createOption + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : null + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + diffDiskSettings: contains(osDisk, 'diffDiskSettings') ? osDisk.diffDiskSettings : null + osType: contains(osDisk, 'osType') ? osDisk.osType : null + image: contains(osDisk, 'image') ? osDisk.image : null + vhdContainers: contains(osDisk, 'vhdContainers') ? osDisk.vhdContainers : null + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? osDisk.managedDisk.diskEncryptionSet : null + } + } + dataDisks: [for (item, j) in dataDisks: { + lun: j + diskSizeGB: item.diskSizeGB + createOption: item.createOption + caching: item.caching + writeAcceleratorEnabled: contains(osDisk, 'writeAcceleratorEnabled') ? osDisk.writeAcceleratorEnabled : null + managedDisk: { + storageAccountType: item.managedDisk.storageAccountType + diskEncryptionSet: { + id: enableServerSideEncryption ? item.managedDisk.diskEncryptionSet.id : null + } + } + diskIOPSReadWrite: contains(osDisk, 'diskIOPSReadWrite') ? item.diskIOPSReadWrite : null + diskMBpsReadWrite: contains(osDisk, 'diskMBpsReadWrite') ? item.diskMBpsReadWrite : null + }] + } + networkProfile: { + networkInterfaceConfigurations: [for (nicConfiguration, index) in nicConfigurations: { + name: '${name}${nicConfiguration.nicSuffix}configuration-${index}' + properties: { + primary: (index == 0) ? true : any(null) + enableAcceleratedNetworking: contains(nicConfigurations, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : null + networkSecurityGroup: contains(nicConfigurations, 'nsgId') ? { + id: nicConfiguration.nsgId + } : null + ipConfigurations: nicConfiguration.ipConfigurations + } + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + licenseType: empty(licenseType) ? null : licenseType + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? json('{"maxPrice":"${maxPriceForLowPriorityVm}"}') : null + scheduledEventsProfile: scheduledEventsProfile + } + overprovision: overprovision + doNotRunExtensionsOnOverprovisionedVMs: doNotRunExtensionsOnOverprovisionedVMs + zoneBalance: zoneBalance == 'true' ? zoneBalance : null + platformFaultDomainCount: scaleSetFaultDomain + singlePlacementGroup: singlePlacementGroup + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + scaleInPolicy: scaleInPolicy + } + sku: { + name: skuName + capacity: skuCapacity + } + plan: !empty(plan) ? plan : null +} + +module vmss_domainJoinExtension 'extensions/deploy.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DomainJoin' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vmss_microsoftAntiMalwareExtension 'extensions/deploy.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftAntiMalware' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +resource vmss_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split(monitoringWorkspaceId, '/')) + scope: resourceGroup(split(monitoringWorkspaceId, '/')[2], split(monitoringWorkspaceId, '/')[4]) +} + +module vmss_microsoftMonitoringAgentExtension 'extensions/deploy.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-MicrosoftMonitoringAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'MicrosoftMonitoringAgent' + publisher: 'Microsoft.EnterpriseCloud.Monitoring' + type: osType == 'Windows' ? 'MicrosoftMonitoringAgent' : 'OmsAgentForLinux' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.7') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vmss_logAnalyticsWorkspace.id, vmss_logAnalyticsWorkspace.apiVersion).customerId : '' + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vmss_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vmss_dependencyAgentExtension 'extensions/deploy.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DependencyAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vmss_networkWatcherAgentExtension 'extensions/deploy.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-NetworkWatcherAgent' + params: { + virtualMachineScaleSetName: vmss.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vmss_desiredStateConfigurationExtension 'extensions/deploy.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DesiredStateConfiguration' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vmss_customScriptExtension 'extensions/deploy.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-CustomScriptExtension' + params: { + virtualMachineScaleSetName: vmss.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: contains(extensionCustomScriptConfig, 'protectedSettings') ? extensionCustomScriptConfig.protectedSettings : {} + enableDefaultTelemetry: enableDefaultTelemetry + } + dependsOn: [ + vmss_desiredStateConfigurationExtension + ] +} + +module vmss_diskEncryptionExtension 'extensions/deploy.bicep' = if (extensionDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VMSS-DiskEncryption' + params: { + virtualMachineScaleSetName: vmss.name + name: 'DiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionDiskEncryptionConfig, 'typeHandlerVersion') ? extensionDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionDiskEncryptionConfig, 'forceUpdateTag') ? extensionDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionDiskEncryptionConfig.settings + enableDefaultTelemetry: enableDefaultTelemetry + } + dependsOn: [ + vmss_customScriptExtension + vmss_microsoftMonitoringAgentExtension + ] +} + +resource vmss_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vmss.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vmss +} + +resource vmss_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: publicIpDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: vmss +} + +module vmss_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VMSS-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: vmss.id + } +}] + +@description('The resource ID of the virtual machine scale set') +output resourceId string = vmss.id + +@description('The resource group of the virtual machine scale set') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual machine scale set') +output name string = vmss.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(vmss.identity, 'principalId') ? vmss.identity.principalId : '' diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep new file mode 100644 index 000000000..c3401b32a --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/deploy.bicep @@ -0,0 +1,77 @@ +@description('Required. The name of the virtual machine scale set that extension is provisioned for') +param virtualMachineScaleSetName string + +@description('Required. The name of the virtual machine scale set extension') +param name string + +@description('Required. The name of the extension handler publisher') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension"') +param type string + +@description('Required. Specifies the version of the script handler') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available') +param enableAutomaticUpgrade bool + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualMachineScaleSet 'Microsoft.Compute/virtualMachineScaleSets@2021-07-01' existing = { + name: virtualMachineScaleSetName +} + +resource extension 'Microsoft.Compute/virtualMachineScaleSets/extensions@2021-07-01' = { + name: name + parent: virtualMachineScaleSet + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The ResourceId of the extension') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md new file mode 100644 index 000000000..35ba89baa --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/readme.md @@ -0,0 +1,51 @@ +# virtual machine scale set Extensions `[Microsoft.Compute/virtualMachineScaleSets/extensions]` + +This module deploys a virtual machine scale set extension. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | 2021-07-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `autoUpgradeMinorVersion` | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true | +| `enableAutomaticUpgrade` | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available | +| `name` | string | The name of the virtual machine scale set extension | +| `publisher` | string | The name of the extension handler publisher | +| `type` | string | Specifies the type of the extension; an example is "CustomScriptExtension" | +| `typeHandlerVersion` | string | Specifies the version of the script handler | +| `virtualMachineScaleSetName` | string | The name of the virtual machine scale set that extension is provisioned for | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `forceUpdateTag` | string | `''` | How the extension handler should be forced to update even if the extension configuration has not changed | +| `protectedSettings` | secureObject | `{object}` | Any object that contains the extension specific protected settings | +| `settings` | object | `{object}` | Any object that contains the extension specific settings | +| `supressFailures` | bool | `False` | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The ResourceId of the extension | + +## Template references + +- [Virtualmachinescalesets/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachineScaleSets/extensions) diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/version.json b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/extensions/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/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/readme.md b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/readme.md new file mode 100644 index 000000000..1c8157ce9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/readme.md @@ -0,0 +1,443 @@ +# Virtual Machine Scale Sets `[Microsoft.Compute/virtualMachineScaleSets]` + +This module deploys a virtual machine scale set. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Compute/proximityPlacementGroups` | 2021-04-01 | +| `Microsoft.Compute/virtualMachineScaleSets` | 2021-04-01 | +| `Microsoft.Compute/virtualMachineScaleSets/extensions` | 2021-07-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- `Microsoft.Network/VirtualNetwork` + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `adminUsername` | secureString | | Administrator username | +| `imageReference` | object | | OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `name` | string | | Name of the VMSS. | +| `nicConfigurations` | array | | Configures NICs and PIPs. | +| `osDisk` | object | | Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| `osType` | string | `[Windows, Linux]` | The chosen OS type | +| `skuName` | string | | The SKU size of the VMs. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | `''` | | When specifying a Windows Virtual Machine, this value should be passed | +| `automaticRepairsPolicyEnabled` | bool | `False` | | Specifies whether automatic repairs should be enabled on the virtual machine scale set. | +| `availabilityZones` | array | `[]` | | The virtual machine scale set zones. NOTE: Availability zones can only be set when you create the scale set. | +| `bootDiagnosticStorageAccountName` | string | `''` | | Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Storage account boot diagnostic base URI. | +| `customData` | string | `''` | | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disableAutomaticRollback` | bool | `False` | | Whether OS image rollback feature should be disabled. | +| `disablePasswordAuthentication` | bool | `False` | | Specifies whether password authentication should be disabled. | +| `doNotRunExtensionsOnOverprovisionedVMs` | bool | `False` | | When Overprovision is enabled, extensions are launched only on the requested number of VMs which are finally kept. This property will hence ensure that the extensions do not run on the extra overprovisioned VMs. | +| `enableAutomaticOSUpgrade` | bool | `False` | | Indicates whether OS upgrades should automatically be applied to scale set instances in a rolling fashion when a newer version of the OS image becomes available. Default value is false. If this is set to true for Windows based scale sets, enableAutomaticUpdates is automatically set to false and cannot be set to true. | +| `enableAutomaticUpdates` | bool | `True` | | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableEvictionPolicy` | bool | `False` | | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | `False` | | Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your virtual machine scale sets. | +| `extensionAntiMalwareConfig` | object | `{object}` | | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDependencyAgentConfig` | object | `{object}` | | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | `''` | | Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `gracePeriod` | string | `'PT30M'` | | The amount of time for which automatic repairs are suspended due to a state change on VM. The grace time starts after the state change has completed. This helps avoid premature or accidental repairs. The time duration should be specified in ISO 8601 format. The minimum allowed grace period is 30 minutes (PT30M). The maximum allowed grace period is 90 minutes (PT90M). | +| `licenseType` | string | `''` | `[Windows_Client, Windows_Server, ]` | Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxBatchInstancePercent` | int | `20` | | The maximum percent of total virtual machine instances that will be upgraded simultaneously by the rolling upgrade in one batch. As this is a maximum, unhealthy instances in previous or future batches can cause the percentage of instances in a batch to decrease to ensure higher reliability. | +| `maxPriceForLowPriorityVm` | string | `''` | | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `maxUnhealthyInstancePercent` | int | `20` | | The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch | +| `maxUnhealthyUpgradedInstancePercent` | int | `20` | | The maximum percentage of the total virtual machine instances in the scale set that can be simultaneously unhealthy, either as a result of being upgraded, or by being found in an unhealthy state by the virtual machine health checks before the rolling upgrade aborts. This constraint will be checked prior to starting any batch. | +| `monitoringWorkspaceId` | string | `''` | | Resource ID of the monitoring log analytics workspace. | +| `overprovision` | bool | `False` | | Specifies whether the Virtual Machine Scale Set should be overprovisioned. | +| `pauseTimeBetweenBatches` | string | `'PT0S'` | | The wait time between completing the update for all virtual machines in one batch and starting the next batch. The time duration should be specified in ISO 8601 format | +| `plan` | object | `{object}` | | Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | `''` | | Creates an proximity placement group and adds the VMs to it. | +| `proximityPlacementGroupType` | string | `'Standard'` | `[Standard, Ultra]` | Specifies the type of the proximity placement group. | +| `publicIpDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `publicKeys` | array | `[]` | | The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sasTokenValidityLength` | string | `'PT8H'` | | SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `scaleInPolicy` | object | `{object}` | | Specifies the scale-in policy that decides which virtual machines are chosen for removal when a Virtual Machine Scale Set is scaled-in | +| `scaleSetFaultDomain` | int | `2` | | Fault Domain count for each placement group. | +| `scheduledEventsProfile` | object | `{object}` | | Specifies Scheduled Event related configurations | +| `secrets` | array | `[]` | | Specifies set of certificates that should be installed onto the virtual machines in the scale set. | +| `secureBootEnabled` | bool | `False` | | Specifies whether secure boot should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `securityType` | string | `''` | | Specifies the SecurityType of the virtual machine scale set. It is set as TrustedLaunch to enable UefiSettings. | +| `singlePlacementGroup` | bool | `True` | | When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true. | +| `skuCapacity` | int | `1` | | The initial instance count of scale set VMs. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `''` | | Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | `False` | | The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `upgradePolicyMode` | string | `'Manual'` | `[Manual, Automatic, Rolling]` | Specifies the mode of an upgrade to virtual machines in the scale set.' Manual - You control the application of updates to virtual machines in the scale set. You do this by using the manualUpgrade action. ; Automatic - All virtual machines in the scale set are automatically updated at the same time. - Automatic, Manual, Rolling | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vmNamePrefix` | string | `'vmssvm'` | | Specifies the computer name prefix for all of the virtual machines in the scale set. | +| `vmPriority` | string | `'Regular'` | `[Regular, Low, Spot]` | Specifies the priority for the virtual machine. | +| `vTpmEnabled` | bool | `False` | | Specifies whether vTPM should be enabled on the virtual machine scale set. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | +| `zoneBalance` | bool | `False` | | Whether to force strictly even Virtual Machine distribution cross x-zones in case there is zone outage. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +#### Marketplace images + +```json +"imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } +} +``` + +#### Custom images + +```json +"imageReference": { + "value": { + "id": "/subscriptions/12345-6789-1011-1213-15161718/resourceGroups/rg-name/providers/Microsoft.Compute/images/imagename" + } +} +``` + +### Parameter Usage: `plan` + +```json +"plan": { + "value": { + "name": "qvsa-25", + "product": "qualys-virtual-scanner", + "publisher": "qualysguard" + } +} +``` + +### Parameter Usage: `osDisk` + +```json + "osDisk": { + "value": { + "createOption": "fromImage", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { // Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VM Scale sets. + "id": "/subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/" + } + } + } +} +``` + +### Parameter Usage: `dataDisks` + +```json +"dataDisks": { + "value": [{ + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "256", + "writeAcceleratorEnabled": true, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "writeAcceleratorEnabled": true, + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }] +} +``` + +### Parameter Usage: `nicConfigurations` + +```json +"nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic01", + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/agents-vmss-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-scaleset/subnets/sxx-az-subnet-scaleset-linux" + } + } + } + ] + } + ] +} +``` + + +### Parameter Usage: `extensionDomainJoinConfig` + + +```json +"windowsScriptExtensionFileData": { + "value": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageAccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageAccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + "secretName": "domainJoinUser-Password" + } +} +``` + +### Parameter Usage: `extensionNetworkWatcherAgentConfig` + +```json +"extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } +} +``` + +### Parameter Usage: `extensionAntiMalwareConfig` + +Only for OSType Windows + +```json +"extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } +} +``` + +### Parameter Usage: `extensionDiskEncryptionConfig` + +```json +"extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://mykeyvault.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionKeyURL": "https://mykeyvault.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", //'RSA-OAEP'/'RSA-OAEP-256'/'RSA1_5' + "VolumeType": "All", //'OS'/'Data'/'All' + "ResizeOSDisk": "false" + } + } +} +``` + +### Parameter Usage: `extensionCustomScriptConfig` + +```json +"extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + //storage account with public container (no SAS token is required) OR other public URL (not a storage account) + { + "uri": "https://github.com/myProject/File3.ps1", + "storageAccountId": "" + } + ], + "settings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File testscript.ps1" + } + } +} +``` + +### Parameter Usage: `extensionDSCConfig` + +```json +"extensionDSCConfig": { + "value": { + { + "enabled": true, + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "http://validURLToConfigLocation", + "script": "ConfigurationScript.ps1", + "function": "ConfigurationFunction" + }, + "configurationArguments": { + "argument1": "Value1", + "argument2": "Value2" + }, + "configurationData": { + "url": "https://foo.psd1" + }, + "privacy": { + "dataCollection": "enable" + }, + "advancedOptions": { + "forcePullAndApply": false, + "downloadMappings": { + "specificDependencyKey": "https://myCustomDependencyLocation" + } + } + }, + "protectedSettings": { + "configurationArguments": { + "mySecret": "MyPlaceholder" + }, + "configurationUrlSasToken": "MyPlaceholder", + "configurationDataUrlSasToken": "MyPlaceholder" + } + } + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual machine scale set | +| `resourceGroupName` | string | The resource group of the virtual machine scale set | +| `resourceId` | string | The resource ID of the virtual machine scale set | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Proximityplacementgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/proximityPlacementGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualmachinescalesets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/virtualMachineScaleSets) +- [Virtualmachinescalesets/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachineScaleSets/extensions) diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/version.json b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachineScaleSets/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/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep new file mode 100644 index 000000000..7e6865bc6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_backup.bicep @@ -0,0 +1,27 @@ +param backupResourceName string + +@allowed([ + 'AzureFileShareProtectedItem' + 'AzureVmWorkloadSAPAseDatabase' + 'AzureVmWorkloadSAPHanaDatabase' + 'AzureVmWorkloadSQLDatabase' + 'DPMProtectedItem' + 'GenericProtectedItem' + 'MabFileFolderProtectedItem' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'Microsoft.Sql/servers/databases' +]) +param protectedItemType string +param backupPolicyId string +param sourceResourceId string + +resource backup 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2021-06-01' = { + name: backupResourceName + location: resourceGroup().location + properties: { + protectedItemType: protectedItemType + policyId: backupPolicyId + sourceResourceId: sourceResourceId + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep new file mode 100644 index 000000000..35df401f8 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_configurationProfileAssignment.bicep @@ -0,0 +1,33 @@ +@description('Optional. The name of the configuration profile assignment') +param name string = 'default' + +@description('Required. The name of the VM to be associated') +param virtualMachineName string + +@description('Required. The configuration profile of automanage') +@allowed([ + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' +]) +param configurationProfile string + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: virtualMachineName +} + +resource configurationProfileAssignment 'Microsoft.Automanage/configurationProfileAssignments@2021-04-30-preview' = { + name: name + properties: { + configurationProfile: configurationProfile + } + scope: virtualMachine +} + +@description('The resource ID of the configuration profile assignment') +output resourceId string = configurationProfileAssignment.id + +@description('The name of the configuration profile assignment') +output name string = configurationProfileAssignment.name + +@description('The resource group the configuration profile assignment was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep new file mode 100644 index 000000000..e7b50c9ed --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface.bicep @@ -0,0 +1,123 @@ +param networkInterfaceName string +param virtualMachineName string +param location string +param tags object +param enableIPForwarding bool = false +param enableAcceleratedNetworking bool = false +param dnsServers array = [] +param networkSecurityGroupId string = '' +param ipConfigurationArray array +param lock string +param diagnosticStorageAccountId string +param diagnosticLogsRetentionInDays int +param diagnosticWorkspaceId string +param diagnosticEventHubAuthorizationRuleId string +param diagnosticEventHubName string +param pipdiagnosticMetricsToEnable array +param pipdiagnosticLogCategoriesToEnable array +param nicDiagnosticMetricsToEnable array +param roleAssignments array + +@description('Optional. The name of the PIP diagnostic setting, if deployed.') +param pipDiagnosticSettingsName string = '${virtualMachineName}-diagnosticSettings' + +@description('Optional. The name of the NIC diagnostic setting, if deployed.') +param nicDiagnosticSettingsName string = '${virtualMachineName}-diagnosticSettings' + +var nicDiagnosticsMetrics = [for metric in nicDiagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module networkInterface_publicIPConfigurations 'nested_networkInterface_publicIPAddress.bicep' = [for (ipConfiguration, index) in ipConfigurationArray: if (contains(ipConfiguration, 'pipconfiguration')) { + name: '${deployment().name}-PIP-${index}' + params: { + publicIPAddressName: '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}' + publicIPPrefixId: (contains(ipConfiguration.pipconfiguration, 'publicIPPrefixId') ? (!(empty(ipConfiguration.pipconfiguration.publicIPPrefixId)) ? ipConfiguration.pipconfiguration.publicIPPrefixId : '') : '') + publicIPAllocationMethod: (contains(ipConfiguration.pipconfiguration, 'publicIPAllocationMethod') ? (!(empty(ipConfiguration.pipconfiguration.publicIPAllocationMethod)) ? ipConfiguration.pipconfiguration.publicIPAllocationMethod : 'Static') : 'Static') + skuName: (contains(ipConfiguration.pipconfiguration, 'skuName') ? (!(empty(ipConfiguration.pipconfiguration.skuName)) ? ipConfiguration.pipconfiguration.skuName : 'Standard') : 'Standard') + skuTier: (contains(ipConfiguration.pipconfiguration, 'skuTier') ? (!(empty(ipConfiguration.pipconfiguration.skuTier)) ? ipConfiguration.pipconfiguration.skuTier : 'Regional') : 'Regional') + location: location + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + diagnosticSettingsName: pipDiagnosticSettingsName + diagnosticMetricsToEnable: pipdiagnosticMetricsToEnable + diagnosticLogCategoriesToEnable: pipdiagnosticLogCategoriesToEnable + lock: lock + roleAssignments: contains(ipConfiguration.pipconfiguration, 'roleAssignments') ? (!empty(ipConfiguration.pipconfiguration.roleAssignments) ? ipConfiguration.pipconfiguration.roleAssignments : []) : [] + tags: tags + } +}] + +resource networkInterface 'Microsoft.Network/networkInterfaces@2021-05-01' = { + name: networkInterfaceName + location: location + tags: tags + properties: { + enableIPForwarding: enableIPForwarding + enableAcceleratedNetworking: enableAcceleratedNetworking + dnsSettings: !empty(dnsServers) ? { + dnsServers: dnsServers + } : null + networkSecurityGroup: !empty(networkSecurityGroupId) ? { + id: networkSecurityGroupId + } : null + ipConfigurations: [for (ipConfiguration, index) in ipConfigurationArray: { + name: !empty(ipConfiguration.name) ? ipConfiguration.name : null + properties: { + primary: ((index == 0) ? true : false) + privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) : null + privateIPAddress: contains(ipConfiguration, 'vmIPAddress') ? (!empty(ipConfiguration.vmIPAddress) ? ipConfiguration.vmIPAddress : null) : null + publicIPAddress: contains(ipConfiguration, 'pipconfiguration') ? json('{"id":"${resourceId('Microsoft.Network/publicIPAddresses', '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}')}"}') : null + subnet: { + id: ipConfiguration.subnetId + } + loadBalancerBackendAddressPools: contains(ipConfiguration, 'loadBalancerBackendAddressPools') ? ipConfiguration.loadBalancerBackendAddressPools : null + applicationSecurityGroups: contains(ipConfiguration, 'applicationSecurityGroups') ? ipConfiguration.applicationSecurityGroups : null + } + }] + } + dependsOn: [ + networkInterface_publicIPConfigurations + ] +} + +resource networkInterface_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkInterface.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkInterface +} + +resource networkInterface_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: nicDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: nicDiagnosticsMetrics + } + scope: networkInterface +} + +module networkInterface_rbac 'nested_networkInterface_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkInterface.id + } +}] diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep new file mode 100644 index 000000000..d8e3494d4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress.bicep @@ -0,0 +1,96 @@ +param publicIPAddressName string +param publicIPPrefixId string +param publicIPAllocationMethod string +param skuName string +param skuTier string +param location string +param diagnosticStorageAccountId string +param diagnosticLogsRetentionInDays int +param diagnosticWorkspaceId string +param diagnosticEventHubAuthorizationRuleId string +param diagnosticEventHubName string +param diagnosticMetricsToEnable array +param diagnosticLogCategoriesToEnable array +param lock string +param roleAssignments array +param tags object + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${publicIPAddressName}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: publicIPAddressName + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + properties: { + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixId) ? { + id: publicIPPrefixId + } : null + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac 'nested_networkInterface_publicIPAddress_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The name of the resource group the public IP address was deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address.') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address.') +output resourceId string = publicIpAddress.id diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep new file mode 100644 index 000000000..87e8e8d34 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_publicIPAddress_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpAddress +}] diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep new file mode 100644 index 000000000..76ae1e208 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_networkInterface_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource networkInterface 'Microsoft.Network/networkInterfaces@2021-03-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkInterface.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: networkInterface +}] diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..700fa4a5b --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualMachine.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualMachine +}] diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json new file mode 100644 index 000000000..2faa09d2f --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/linux.min.parameters.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-linux-min-01" + }, + "osType": { + "value": "Linux" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + } + } + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json new file mode 100644 index 000000000..8938e6f7a --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/linux.parameters.json @@ -0,0 +1,220 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-linux-01" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "osType": { + "value": "Linux" + }, + "encryptionAtHost": { + "value": false + }, + "availabilityZone": { + "value": 1 + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "caching": "ReadOnly", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "dataDisks": { + "value": [ + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "ReadWrite", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "ReadWrite", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "loadBalancerBackendAddressPools": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" + } + ], + "applicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ] + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "backupVaultName": { + "value": "adp-<>-az-rsv-x-001" + }, + "backupVaultResourceGroup": { + "value": "validation-rg" + }, + "backupPolicyName": { + "value": "VMpolicy" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "monitoringWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": false + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ] + } + }, + "extensionCustomScriptProtectedSetting": { + "value": { + "commandToExecute": "sudo apt-get update" + } + }, + "configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json new file mode 100644 index 000000000..499379aba --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/windows.min.parameters.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "adminUsername": { + "value": "localAdminUser" + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + } + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json new file mode 100644 index 000000000..632de7554 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/.parameters/windows.parameters.json @@ -0,0 +1,237 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-vm-win-01" + }, + "encryptionAtHost": { + "value": false + }, + "imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "caching": "None", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "dataDisks": { + "value": [ + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "None", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "createOption": "Empty", + "deleteOption": "Delete", + "caching": "None", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "availabilityZone": { + "value": 2 + }, + "adminUsername": { + "value": "localAdminUser" + }, + "adminPassword": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "adminPassword" + } + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "loadBalancerBackendAddressPools": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" + } + ], + "applicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ] + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "backupVaultName": { + "value": "adp-<>-az-rsv-x-001" + }, + "backupVaultResourceGroup": { + "value": "validation-rg" + }, + "backupPolicyName": { + "value": "VMpolicy" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": "true", + "Exclusions": { + "Extensions": ".ext1;.ext2", + "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", + "Processes": "excludedproc1.exe;excludedproc2.exe" + }, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true + } + }, + "monitoringWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true + } + }, + "extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "VolumeType": "All", + "ResizeOSDisk": "false" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", + "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + } + ] + } + }, + "extensionCustomScriptProtectedSetting": { + "value": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + } + }, + "configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/deploy.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/deploy.bicep new file mode 100644 index 000000000..9c4eff24b --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/deploy.bicep @@ -0,0 +1,647 @@ +// Main resource +@description('Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group\'s name.') +param name string = take(toLower(uniqueString(resourceGroup().name)), 10) + +@description('Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are \'none\' (Default), \'uppercase\' and \'lowercase\'.') +param vmComputerNamesTransformation string = 'none' + +@description('Required. Specifies the size for the VMs') +param vmSize string + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machine.') +param certificatesToBeInstalled array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies resource ID about the dedicated host that the virtual machine resides in.') +param dedicatedHostId string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Resource name of a proximity placement group.') +param proximityPlacementGroupName string = '' + +@description('Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set.') +param availabilitySetName string = '' + +@description('Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set.') +param availabilityZone array + +// External resources +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array + +@description('Optional. The name of the PIP diagnostic setting, if deployed.') +param pipDiagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param pipdiagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param pipdiagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the NIC diagnostic setting, if deployed.') +param nicDiagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param nicdiagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. Recovery service vault name to add VMs to backup.') +param backupVaultName string = '' + +@description('Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default.') +param backupVaultResourceGroup string = resourceGroup().name + +@description('Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault.') +param backupPolicyName string = 'DefaultPolicy' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +// Child resources +@description('Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine.') +param allowExtensionOperations bool = true + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param extensionCustomScriptProtectedSetting object = {} + +// Shared parameters +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Any VM configuration profile assignments') +param configurationProfileAssignments array = [] + +var vmComputerNameTransformed = vmComputerNamesTransformation == 'uppercase' ? toUpper(name) : (vmComputerNamesTransformation == 'lowercase' ? toLower(name) : name) + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module virtualMachine_nic '.bicep/nested_networkInterface.bicep' = [for (nicConfiguration, index) in nicConfigurations: { + name: '${uniqueString(deployment().name, location)}-VM-Nic-${index}' + params: { + networkInterfaceName: '${name}${nicConfiguration.nicSuffix}' + virtualMachineName: name + location: location + tags: tags + enableIPForwarding: contains(nicConfiguration, 'enableIPForwarding') ? (!empty(nicConfiguration.enableIPForwarding) ? nicConfiguration.enableIPForwarding : false) : false + enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true + dnsServers: contains(nicConfiguration, 'dnsServers') ? (!empty(nicConfiguration.dnsServers) ? nicConfiguration.dnsServers : []) : [] + networkSecurityGroupId: contains(nicConfiguration, 'nsgId') ? (!empty(nicConfiguration.nsgId) ? nicConfiguration.nsgId : '') : '' + ipConfigurationArray: nicConfiguration.ipConfigurations + lock: lock + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + pipDiagnosticSettingsName: pipDiagnosticSettingsName + nicDiagnosticSettingsName: nicDiagnosticSettingsName + pipdiagnosticMetricsToEnable: pipdiagnosticMetricsToEnable + pipdiagnosticLogCategoriesToEnable: pipdiagnosticLogCategoriesToEnable + nicDiagnosticMetricsToEnable: nicdiagnosticMetricsToEnable + roleAssignments: contains(nicConfiguration, 'roleAssignments') ? (!empty(nicConfiguration.roleAssignments) ? nicConfiguration.roleAssignments : []) : [] + } +}] + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' = { + name: name + location: location + identity: identity + tags: tags + zones: availabilityZone == '' ? null : availabilityZone + plan: !empty(plan) ? plan : null + properties: { + hardwareProfile: { + vmSize: vmSize + } + securityProfile: { + encryptionAtHost: encryptionAtHost ? encryptionAtHost : null + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + name: '${name}-disk-os-01' + createOption: contains(osDisk, 'createOption') ? osDisk.createOption : 'FromImage' + deleteOption: contains(osDisk, 'deleteOption') ? osDisk.deleteOption : 'Delete' + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : 'ReadOnly' + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? osDisk.managedDisk.diskEncryptionSet : null + } + } + dataDisks: [for (dataDisk, index) in dataDisks: { + lun: index + name: '${name}-disk-data-${padLeft((index + 1), 2, '0')}' + diskSizeGB: dataDisk.diskSizeGB + createOption: contains(dataDisk, 'createOption') ? dataDisk.createOption : 'Empty' + deleteOption: contains(dataDisk, 'deleteOption') ? dataDisk.deleteOption : 'Delete' + caching: contains(dataDisk, 'caching') ? dataDisk.caching : 'ReadOnly' + managedDisk: { + storageAccountType: dataDisk.managedDisk.storageAccountType + diskEncryptionSet: { + id: enableServerSideEncryption ? dataDisk.managedDisk.diskEncryptionSet.id : null + } + } + }] + } + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + osProfile: { + computerName: vmComputerNameTransformed + adminUsername: adminUsername + adminPassword: adminPassword + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: certificatesToBeInstalled + allowExtensionOperations: allowExtensionOperations + } + networkProfile: { + networkInterfaces: [for (nicConfiguration, index) in nicConfigurations: { + properties: { + deleteOption: contains(nicConfiguration, 'deleteOption') ? nicConfiguration.deleteOption : 'Delete' + primary: index == 0 ? true : false + } + id: az.resourceId('Microsoft.Network/networkInterfaces', '${name}${nicConfiguration.nicSuffix}') + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + availabilitySet: !empty(availabilitySetName) ? json('{"id":"${az.resourceId('Microsoft.Compute/availabilitySets', availabilitySetName)}"}') : null + proximityPlacementGroup: !empty(proximityPlacementGroupName) ? json('{"id":"${az.resourceId('Microsoft.Compute/proximityPlacementGroups', proximityPlacementGroupName)}"}') : null + priority: vmPriority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(vmPriority) && !empty(maxPriceForLowPriorityVm) ? json('{"maxPrice":"${maxPriceForLowPriorityVm}"}') : null + host: !empty(dedicatedHostId) ? json('{"id":"${dedicatedHostId}"}') : null + licenseType: !empty(licenseType) ? licenseType : null + } + dependsOn: [ + virtualMachine_nic + ] +} + +module vm_configurationProfileAssignment '.bicep/nested_configurationProfileAssignment.bicep' = [for (configurationProfileAssignment, index) in configurationProfileAssignments: { + name: '${uniqueString(deployment().name, location)}-VM-ConfigurationProfileAssignment-${index}' + params: { + virtualMachineName: virtualMachine.name + configurationProfile: configurationProfileAssignment + } +}] + +module vm_domainJoinExtension 'extensions/deploy.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DomainJoin' + params: { + virtualMachineName: virtualMachine.name + name: 'DomainJoin' + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + protectedSettings: { + Password: extensionDomainJoinPassword + } + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vm_microsoftAntiMalwareExtension 'extensions/deploy.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftAntiMalware' + params: { + virtualMachineName: virtualMachine.name + name: 'MicrosoftAntiMalware' + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +resource vm_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { + name: last(split(monitoringWorkspaceId, '/')) + scope: az.resourceGroup(split(monitoringWorkspaceId, '/')[2], split(monitoringWorkspaceId, '/')[4]) +} + +module vm_microsoftMonitoringAgentExtension 'extensions/deploy.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftMonitoringAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'MicrosoftMonitoringAgent' + publisher: 'Microsoft.EnterpriseCloud.Monitoring' + type: osType == 'Windows' ? 'MicrosoftMonitoringAgent' : 'OmsAgentForLinux' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.7') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : false + settings: { + workspaceId: !empty(monitoringWorkspaceId) ? reference(vm_logAnalyticsWorkspace.id, vm_logAnalyticsWorkspace.apiVersion).customerId : '' + } + protectedSettings: { + workspaceKey: !empty(monitoringWorkspaceId) ? vm_logAnalyticsWorkspace.listKeys().primarySharedKey : '' + } + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vm_dependencyAgentExtension 'extensions/deploy.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DependencyAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'DependencyAgent' + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vm_networkWatcherAgentExtension 'extensions/deploy.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-NetworkWatcherAgent' + params: { + virtualMachineName: virtualMachine.name + name: 'NetworkWatcherAgent' + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vm_desiredStateConfigurationExtension 'extensions/deploy.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DesiredStateConfiguration' + params: { + virtualMachineName: virtualMachine.name + name: 'DesiredStateConfiguration' + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module vm_customScriptExtension 'extensions/deploy.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-CustomScriptExtension' + params: { + virtualMachineName: virtualMachine.name + name: 'CustomScriptExtension' + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + protectedSettings: extensionCustomScriptProtectedSetting + enableDefaultTelemetry: enableDefaultTelemetry + } + dependsOn: [ + vm_desiredStateConfigurationExtension + ] +} + +module vm_diskEncryptionExtension 'extensions/deploy.bicep' = if (extensionDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DiskEncryption' + params: { + virtualMachineName: virtualMachine.name + name: 'DiskEncryption' + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionDiskEncryptionConfig, 'typeHandlerVersion') ? extensionDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionDiskEncryptionConfig, 'forceUpdateTag') ? extensionDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionDiskEncryptionConfig.settings + enableDefaultTelemetry: enableDefaultTelemetry + } + dependsOn: [ + vm_customScriptExtension + vm_microsoftMonitoringAgentExtension + ] +} + +module virtualMachine_backup '.bicep/nested_backup.bicep' = if (!empty(backupVaultName)) { + name: '${uniqueString(deployment().name, location)}-VM-Backup' + params: { + backupResourceName: '${backupVaultName}/Azure/iaasvmcontainer;iaasvmcontainerv2;${resourceGroup().name};${virtualMachine.name}/vm;iaasvmcontainerv2;${resourceGroup().name};${virtualMachine.name}' + protectedItemType: 'Microsoft.Compute/virtualMachines' + backupPolicyId: az.resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', backupVaultName, backupPolicyName) + sourceResourceId: virtualMachine.id + } + scope: az.resourceGroup(backupVaultResourceGroup) + dependsOn: [ + vm_domainJoinExtension + vm_microsoftMonitoringAgentExtension + vm_microsoftAntiMalwareExtension + vm_networkWatcherAgentExtension + vm_dependencyAgentExtension + vm_desiredStateConfigurationExtension + vm_customScriptExtension + ] +} + +resource virtualMachine_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualMachine.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualMachine +} + +module virtualMachine_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VM-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualMachine.id + } +}] + +@description('The name of the VM.') +output name string = virtualMachine.name + +@description('The resource ID of the VM.') +output resourceId string = virtualMachine.id + +@description('The name of the resource group the VM was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(virtualMachine.identity, 'principalId') ? virtualMachine.identity.principalId : '' diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/deploy.bicep b/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/deploy.bicep new file mode 100644 index 000000000..b0ec0ffb4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/deploy.bicep @@ -0,0 +1,81 @@ +@description('Required. The name of the virtual machine that extension is provisioned for') +param virtualMachineName string + +@description('Required. The name of the virtual machine extension') +param name string + +@description('Optional. The location the extension is deployed to') +param location string = resourceGroup().location + +@description('Required. The name of the extension handler publisher') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension"') +param type string + +@description('Required. Specifies the version of the script handler') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed') +param forceUpdateTag string = '' + +@description('Optional. Any object that contains the extension specific settings') +param settings object = {} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param protectedSettings object = {} + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available') +param enableAutomaticUpgrade bool + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-07-01' existing = { + name: virtualMachineName +} + +resource extension 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: name + parent: virtualMachine + location: location + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag: !empty(forceUpdateTag) ? forceUpdateTag : null + settings: !empty(settings) ? settings : null + protectedSettings: !empty(protectedSettings) ? protectedSettings : null + suppressFailures: supressFailures + } +} + +@description('The name of the extension') +output name string = extension.name + +@description('The resource ID of the extension') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/readme.md b/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/readme.md new file mode 100644 index 000000000..77341a1ef --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/readme.md @@ -0,0 +1,52 @@ +# Virtual Machine Extensions `[Microsoft.Compute/virtualMachines/extensions]` + +This module deploys a virtual machine extension. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachines/extensions` | 2021-07-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `autoUpgradeMinorVersion` | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true | +| `enableAutomaticUpgrade` | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available | +| `name` | string | The name of the virtual machine extension | +| `publisher` | string | The name of the extension handler publisher | +| `type` | string | Specifies the type of the extension; an example is "CustomScriptExtension" | +| `typeHandlerVersion` | string | Specifies the version of the script handler | +| `virtualMachineName` | string | The name of the virtual machine that extension is provisioned for | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `forceUpdateTag` | string | `''` | How the extension handler should be forced to update even if the extension configuration has not changed | +| `location` | string | `[resourceGroup().location]` | The location the extension is deployed to | +| `protectedSettings` | secureObject | `{object}` | Any object that contains the extension specific protected settings | +| `settings` | object | `{object}` | Any object that contains the extension specific settings | +| `supressFailures` | bool | `False` | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the extension | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The resource ID of the extension | + +## Template references + +- [Virtualmachines/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/version.json b/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/extensions/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/carml/1.2.0/Microsoft.Compute/virtualMachines/readme.md b/carml/1.2.0/Microsoft.Compute/virtualMachines/readme.md new file mode 100644 index 000000000..d7ea5bcd9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/readme.md @@ -0,0 +1,562 @@ +# Virtual Machines `[Microsoft.Compute/virtualMachines]` + +This module deploys one Virtual Machine with one or multiple nics and optionally one or multiple public IPs. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Automanage/configurationProfileAssignments` | 2021-04-30-preview | +| `Microsoft.Compute/virtualMachines` | 2021-07-01 | +| `Microsoft.Compute/virtualMachines/extensions` | 2021-07-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/networkInterfaces` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `adminUsername` | secureString | | Administrator username | +| `imageReference` | object | | OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `nicConfigurations` | array | | Configures NICs and PIPs. | +| `osDisk` | object | | Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `osType` | string | `[Windows, Linux]` | The chosen OS type | +| `vmSize` | string | | Specifies the size for the VMs | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | `''` | | When specifying a Windows Virtual Machine, this value should be passed | +| `allowExtensionOperations` | bool | `True` | | Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine. | +| `availabilitySetName` | string | `''` | | Resource name of an availability set. Cannot be used in combination with availability zone nor scale set. | +| `availabilityZone` | int | `0` | `[0, 1, 2, 3]` | If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set. | +| `backupPolicyName` | string | `'DefaultPolicy'` | | Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. | +| `backupVaultName` | string | `''` | | Recovery service vault name to add VMs to backup. | +| `backupVaultResourceGroup` | string | `[resourceGroup().name]` | | Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. | +| `bootDiagnosticStorageAccountName` | string | `''` | | Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Storage account boot diagnostic base URI. | +| `certificatesToBeInstalled` | array | `[]` | | Specifies set of certificates that should be installed onto the virtual machine. | +| `configurationProfileAssignments` | array | `[]` | | Any VM configuration profile assignments | +| `customData` | string | `''` | | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `dedicatedHostId` | string | `''` | | Specifies resource ID about the dedicated host that the virtual machine resides in. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disablePasswordAuthentication` | bool | `False` | | Specifies whether password authentication should be disabled. | +| `enableAutomaticUpdates` | bool | `True` | | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableEvictionPolicy` | bool | `False` | | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | `False` | | Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `extensionAntiMalwareConfig` | object | `{object}` | | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptProtectedSetting` | secureObject | `{object}` | | Any object that contains the extension specific protected settings | +| `extensionDependencyAgentConfig` | object | `{object}` | | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | `''` | | Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `licenseType` | string | `''` | `[Windows_Client, Windows_Server, ]` | Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxPriceForLowPriorityVm` | string | `''` | | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `monitoringWorkspaceId` | string | `''` | | Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true. | +| `name` | string | `[take(toLower(uniqueString(resourceGroup().name)), 10)]` | | The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name. | +| `nicdiagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `nicDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the NIC diagnostic setting, if deployed. | +| `pipdiagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `pipdiagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `pipDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the PIP diagnostic setting, if deployed. | +| `plan` | object | `{object}` | | Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | `''` | | Resource name of a proximity placement group. | +| `publicKeys` | array | `[]` | | The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sasTokenValidityLength` | string | `'PT8H'` | | SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `secureBootEnabled` | bool | `False` | | Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `securityType` | string | `''` | | Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `''` | | Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | `False` | | The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vmComputerNamesTransformation` | string | `'none'` | | Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'. | +| `vmPriority` | string | `'Regular'` | `[Regular, Low, Spot]` | Specifies the priority for the virtual machine. | +| `vTpmEnabled` | bool | `False` | | Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +### Parameter Usage: `imageReference` + +#### Marketplace images + +```json +"imageReference": { + "value": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2016-Datacenter", + "version": "latest" + } +} +``` + +#### Custom images + +```json +"imageReference": { + "value": { + "id": "/subscriptions/12345-6789-1011-1213-15161718/resourceGroups/rg-name/providers/Microsoft.Compute/images/imagename" + } +} +``` + +### Parameter Usage: `plan` + +```json +"plan": { + "value": { + "name": "qvsa-25", + "product": "qualys-virtual-scanner", + "publisher": "qualysguard" + } +} +``` + +### Parameter Usage: `osDisk` + +```json + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { // Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. + "id": "/subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/" + } + } + } +} +``` + +### Parameter Usage: `dataDisks` + +```json +"dataDisks": { + "value": [{ + "caching": "ReadOnly", + "createOption": "Empty", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "diskSizeGB": "256", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }] +} +``` + +### Parameter Usage: `windowsConfiguration` + +To set the time zone of a VM with the timeZone parameter inside windowsConfiguration, use the following PS command to get the correct options: + +```powershell +Get-TimeZone -ListAvailable | Select ID +``` + +```json +"windowsConfiguration": { + "provisionVMAgent": "boolean", + "enableAutomaticUpdates": "boolean", + "timeZone": "string", + "additionalUnattendContent": [ + { + "passName": "OobeSystem", + "componentName": "Microsoft-Windows-Shell-Setup", + "settingName": "string", + "content": "string" + } + ], + "winRM": { + "listeners": [ + { + "protocol": "string", + "certificateUrl": "string" + } + ] + } +} +``` + +### Parameter Usage: `linuxConfiguration` + +```json +"linuxConfiguration": { + "disablePasswordAuthentication": "boolean", + "ssh": { + "publicKeys": [ + { + "path": "string", + "keyData": "string" + } + ] + }, + "provisionVMAgent": "boolean" + }, + "secrets": [ + { + "sourceVault": { + "id": "string" + }, + "vaultCertificates": [ + { + "certificateUrl": "string", + "certificateStore": "string" + } + ] + } + ], + "allowExtensionOperations": "boolean", + "requireGuestProvisionSignal": "boolean" +} +``` + +### Parameter Usage: `nicConfigurations` + +Comments: +- The field `nicSuffix` and `subnetId` are mandatory. +- If `enablePublicIP` is set to true, then `publicIpNameSuffix` is also mandatory. +- Each IP config needs to have the mandatory field `name`. +- If not disabled, `enableAcceleratedNetworking` is considered `true` by default and requires the VM to be deployed with a supported OS and VM size. + +```json +"nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", // Optional. Can be 'Delete' or 'Detach' + "ipConfigurations": [ + { + "name": "ipconfig1", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "" + ] + } + ] + } + }, + { + "name": "ipconfig2", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + } + ], + "nsgId": "/subscriptions//resourceGroups//providers/Microsoft.Network/networkSecurityGroups/", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "" + ] + } + ] + }, + { + "nicSuffix": "-nic-02", + "ipConfigurations": [ + { + "name": "ipconfig1", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-02" + } + }, + { + "name": "ipconfig2", + "subnetId": "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/", + "privateIPAllocationMethod": "Static", + "vmIPAddress": "10.0.0.9" + } + ] + } + ] +} +``` + +### Parameter Usage: `configurationProfileAssignments` + +```json +"configurationProfileAssignments": { + "value": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest" + ] +} +``` + +### Parameter Usage: `extensionDomainJoinConfig` + +```json +"extensionDomainJoinConfig": { + "value": { + "enabled": true, + "settings": { + "domainName": "contoso.com", + "domainJoinUser": "test.user@testcompany.com", + "domainJoinOU": "OU=testOU; DC=contoso; DC=com", + "domainJoinRestart": true, + "domainJoinOptions": 3 + } + } +}, +"extensionDomainJoinPassword": { + "keyVault": { + "id": "/subscriptions/62826c76-d304-46d8-a0f6-718dbdcc536c/resourceGroups/WVD-Mgmt-TO-RG/providers/Microsoft.KeyVault/vaults/wvd-to-kvlt" + }, + "secretName": "domainJoinUser02-Password" +} +``` + +### Parameter Usage: `extensionAntiMalwareConfig` + +Only for OSType Windows + +```json +"extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "Exclusions": { + "Extensions": ".log;.ldf", + "Paths": "D:\\IISlogs;D:\\DatabaseLogs", + "Processes": "mssence.svc" + }, + "RealtimeProtectionEnabled": true, + "ScheduledScanSettings": { + "isEnabled": "true", + "scanType": "Quick", + "day": "7", + "time": "120" + } + } + } +} +``` + +### Parameter Usage: `extensionDiskEncryptionConfig` + +```json +"extensionDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KeyVaultURL": "https://mykeyvault.vault.azure.net/", + "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionKeyURL": "https://mykeyvault.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys + "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-sxx-az-kv-x-001", + "KeyEncryptionAlgorithm": "RSA-OAEP", //'RSA-OAEP'/'RSA-OAEP-256'/'RSA1_5' + "VolumeType": "All", //'OS'/'Data'/'All' + "ResizeOSDisk": "false" + } + } +} +``` + +### Parameter Usage: `extensionDSCConfig` + +```json +"extensionDSCConfig": { + "value": { + { + "enabled": true, + "settings": { + "wmfVersion": "latest", + "configuration": { + "url": "http://validURLToConfigLocation", + "script": "ConfigurationScript.ps1", + "function": "ConfigurationFunction" + }, + "configurationArguments": { + "argument1": "Value1", + "argument2": "Value2" + }, + "configurationData": { + "url": "https://foo.psd1" + }, + "privacy": { + "dataCollection": "enable" + }, + "advancedOptions": { + "forcePullAndApply": false, + "downloadMappings": { + "specificDependencyKey": "https://myCustomDependencyLocation" + } + } + }, + "protectedSettings": { + "configurationArguments": { + "mySecret": "MyPlaceholder" + }, + "configurationUrlSasToken": "MyPlaceholder", + "configurationDataUrlSasToken": "MyPlaceholder" + } + } + } +} +``` + +### Parameter Usage: `extensionCustomScriptConfig` + +```json +"extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + //storage accounts with SAS token requirement + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File1.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + { + "uri": "https://mystorageaccount.blob.core.windows.net/avdscripts/File2.ps1", + "storageAccountId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rgName/providers/Microsoft.Storage/storageAccounts/storageAccountName" + }, + //storage account with public container (no SAS token is required) OR other public URL (not a storage account) + { + "uri": "https://github.com/myProject/File3.ps1", + "storageAccountId": "" + } + ], + "settings": { + "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File testscript.ps1" + } + } +} +``` + +### Parameter Usage: `extensionCustomScriptProtectedSetting` + +This is used if you are going to use secrets or other sensitive information that you don't want to be visible in the deployment and logs. + +```json +"extensionCustomScriptProtectedSetting": { + "value": [ + "commandToExecute": "mycommandToRun -someParam MYSECRET" + ] +} +``` +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VM. | +| `resourceGroupName` | string | The name of the resource group the VM was created in. | +| `resourceId` | string | The resource ID of the VM. | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Define resources with Bicep and ARM templates](https://docs.microsoft.com/en-us/azure/templates) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networkinterfaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkInterfaces) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Backupfabrics/Protectioncontainers/Protecteditems](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-06-01/vaults/backupFabrics/protectionContainers/protectedItems) +- [Virtualmachines](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines) +- [Virtualmachines/Extensions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) diff --git a/carml/1.2.0/Microsoft.Compute/virtualMachines/version.json b/carml/1.2.0/Microsoft.Compute/virtualMachines/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Compute/virtualMachines/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/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..1cb9dbf6f --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63') + 'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b') + 'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationgroups@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(appGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: appGroup +}] diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/min.parameters.json new file mode 100644 index 000000000..ecf7a145e --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/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": { + "name": { + "value": "<>-az-avdag-min-001" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "adp-<>-az-avdhp-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json new file mode 100644 index 000000000..2b43fed10 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/.parameters/parameters.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdag-x-001" + }, + "location": { + "value": "westeurope" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "adp-<>-az-avdhp-x-001" + }, + "friendlyName": { + "value": "Remote Applications 1" + }, + "description": { + "value": "This is my first Remote Applications bundle" + }, + "applications": { + "value": [ + { + "name": "notepad", + "description": "Notepad by ARM template", + "friendlyName": "Notepad", + "filePath": "C:\\Windows\\System32\\notepad.exe", + "commandLineSetting": "DoNotAllow", + "commandLineArguments": "", + "showInPortal": true, + "iconPath": "C:\\Windows\\System32\\notepad.exe", + "iconIndex": 0 + }, + { + "name": "wordpad", + "filePath": "C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe", + "friendlyName": "Wordpad" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep new file mode 100644 index 000000000..d63d26667 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/deploy.bicep @@ -0,0 +1,77 @@ +@sys.description('Required. Name of the Application Group to create the application(s) in.') +param appGroupName string + +@sys.description('Required. Name of the Application to be created in the Application Group.') +param name string + +@sys.description('Optional. Description of Application..') +param description string = '' + +@sys.description('Required. Friendly name of Application..') +param friendlyName string + +@sys.description('Required. Specifies a path for the executable file for the application.') +param filePath string + +@allowed([ + 'Allow' + 'DoNotAllow' + 'Require' +]) +@sys.description('Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all.') +param commandLineSetting string = 'DoNotAllow' + +@sys.description('Optional. Command-Line Arguments for Application.') +param commandLineArguments string = '' + +@sys.description('Optional. Specifies whether to show the RemoteApp program in the RD Web Access server.') +param showInPortal bool = false + +@sys.description('Optional. Path to icon.') +param iconPath string = '' + +@sys.description('Optional. Index of the icon.') +param iconIndex int = 0 + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource applicationGroup 'Microsoft.DesktopVirtualization/applicationGroups@2021-09-03-preview' existing = { + name: appGroupName +} + +resource application 'Microsoft.DesktopVirtualization/applicationGroups/applications@2021-07-12' = { + name: name + parent: applicationGroup + properties: { + description: description + friendlyName: friendlyName + filePath: filePath + commandLineSetting: commandLineSetting + commandLineArguments: commandLineArguments + showInPortal: showInPortal + iconPath: iconPath + iconIndex: iconIndex + } +} + +@sys.description('The resource ID of the deployed Application.') +output applicationResourceIds string = application.id + +@sys.description('The name of the Resource Group the AVD Application was created in.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The Name of the Application Group to register the Application in.') +output name string = appGroupName diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md new file mode 100644 index 000000000..87ea0b738 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/readme.md @@ -0,0 +1,50 @@ +# AVD Applications `[Microsoft.DesktopVirtualization/applicationGroups/applications]` + +This module deploys AVD Applications. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | 2021-07-12 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `appGroupName` | string | Name of the Application Group to create the application(s) in. | +| `filePath` | string | Specifies a path for the executable file for the application. | +| `friendlyName` | string | Friendly name of Application.. | +| `name` | string | Name of the Application to be created in the Application Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `commandLineArguments` | string | `''` | | Command-Line Arguments for Application. | +| `commandLineSetting` | string | `'DoNotAllow'` | `[Allow, DoNotAllow, Require]` | Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all. | +| `description` | string | `''` | | Description of Application.. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `iconIndex` | int | `0` | | Index of the icon. | +| `iconPath` | string | `''` | | Path to icon. | +| `showInPortal` | bool | `False` | | Specifies whether to show the RemoteApp program in the RD Web Access server. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationResourceIds` | string | The resource ID of the deployed Application. | +| `name` | string | The Name of the Application Group to register the Application in. | +| `resourceGroupName` | string | The name of the Resource Group the AVD Application was created in. | + +## Template references + +- [Applicationgroups/Applications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups/applications) diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/version.json b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/applications/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/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep new file mode 100644 index 000000000..8885f6c25 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep @@ -0,0 +1,169 @@ +@sys.description('Required. Name of the Application Group to create this application in.') +@minLength(1) +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop') +@allowed([ + 'RemoteApp' + 'Desktop' +]) +param applicationGroupType string + +@sys.description('Required. Name of the Host Pool to be linked to this Application Group.') +param hostpoolName string + +@sys.description('Optional. The friendly name of the Application Group to be created.') +param friendlyName string = '' + +@sys.description('Optional. The description of the Application Group to be created.') +param description string = '' + +@sys.description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@sys.description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@sys.description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@sys.description('Optional. Resource ID of log analytics.') +param diagnosticWorkspaceId string = '' + +@sys.description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@sys.description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@sys.description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@sys.description('Optional. Tags of the resource.') +param tags object = {} + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' +] + +@sys.description('Optional. List of applications to be created in the Application Group.') +param applications array = [] + +@sys.description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource appGroup_hostpool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: hostpoolName +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationgroups@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + hostPoolArmPath: appGroup_hostpool.id + friendlyName: friendlyName + description: description + applicationGroupType: applicationGroupType + } +} + +resource appGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${appGroup.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: appGroup +} + +resource appGroup_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: appGroup +} + +module appGroup_applications 'applications/deploy.bicep' = [for (application, index) in applications: { + name: '${uniqueString(deployment().name, location)}-AppGroup-App-${index}' + params: { + name: application.name + appGroupName: appGroup.name + description: contains(application, 'description') ? application.description : '' + friendlyName: contains(application, 'friendlyName') ? application.friendlyName : appGroup.name + filePath: application.filePath + commandLineSetting: contains(application, 'commandLineSetting') ? application.commandLineSetting : 'DoNotAllow' + commandLineArguments: contains(application, 'commandLineArguments') ? application.commandLineArguments : '' + showInPortal: contains(application, 'showInPortal') ? application.showInPortal : false + iconPath: contains(application, 'iconPath') ? application.iconPath : application.filePath + iconIndex: contains(application, 'iconIndex') ? application.iconIndex : 0 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module appGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: appGroup.id + } +}] + +@sys.description('The resource ID of the AVD application group') +output resourceId string = appGroup.id + +@sys.description('The resource group the AVD application group was deployed into') +output resourceGroupName string = resourceGroup().name + +@sys.description('The name of the AVD application group') +output name string = appGroup.name diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/readme.md b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/readme.md new file mode 100644 index 000000000..750713e79 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/readme.md @@ -0,0 +1,108 @@ +# AVD Application Groups `[Microsoft.DesktopVirtualization/applicationgroups]` + +This module deploys an Azure virtual desktop application group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/applicationGroups` | 2021-07-12 | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `applicationGroupType` | string | `[RemoteApp, Desktop]` | The type of the Application Group to be created. Allowed values: RemoteApp or Desktop | +| `hostpoolName` | string | | Name of the Host Pool to be linked to this Application Group. | +| `name` | string | | Name of the Application Group to create this application in. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `applications` | _[applications](applications/readme.md)_ array | `[]` | | List of applications to be created in the Application Group. | +| `description` | string | `''` | | The description of the Application Group to be created. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Checkpoint, Error, Management]` | `[Checkpoint, Error, Management]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of log analytics. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `friendlyName` | string | `''` | | The friendly name of the Application Group to be created. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD application group | +| `resourceGroupName` | string | The resource group the AVD application group was deployed into | +| `resourceId` | string | The resource ID of the AVD application group | + +## Template references + +- [Applicationgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups) +- [Applicationgroups/Applications](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/applicationGroups/applications) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/version.json b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/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/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..bc1b6b328 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Host Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc') + 'Desktop Virtualization Host Pool Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Session Host Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408') + 'Desktop Virtualization User Session Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(hostPool.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: hostPool +}] diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json new file mode 100644 index 000000000..ba8ef0e1f --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/.parameters/parameters.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdhp-x-001" + }, + "location": { + "value": "westeurope" + }, + "hostpoolFriendlyName": { + "value": "AVDv2" + }, + "hostpoolDescription": { + "value": "My first AVD Host Pool" + }, + "hostpoolType": { + "value": "Pooled" + }, + "personalDesktopAssignmentType": { + "value": "Automatic" + }, + "maxSessionLimit": { + "value": 99999 + }, + "loadBalancerType": { + "value": "BreadthFirst" + }, + "customRdpProperty": { + "value": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;" + }, + "vmTemplate": { + "value": { + "domain": "domainname.onmicrosoft.com", + "galleryImageOffer": "office-365", + "galleryImagePublisher": "microsoftwindowsdesktop", + "galleryImageSKU": "20h1-evd-o365pp", + "imageType": "Gallery", + "imageUri": null, + "customImageId": null, + "namePrefix": "avdv2", + "osDiskType": "StandardSSD_LRS", + "useManagedDisks": true, + "vmSize": { + "id": "Standard_D2s_v3", + "cores": 2, + "ram": 8 + } + } + }, + "validationEnviroment": { + "value": false + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep new file mode 100644 index 000000000..207ff2b56 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep @@ -0,0 +1,216 @@ +@description('Required. Name of the Host Pool') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The friendly name of the Host Pool to be created.') +param hostpoolFriendlyName string = '' + +@description('Optional. The description of the Host Pool to be created.') +param hostpoolDescription string = '' + +@description('Optional. Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled.') +@allowed([ + 'Personal' + 'Pooled' +]) +param hostpoolType string = 'Pooled' + +@description('Optional. Set the type of assignment for a Personal Host Pool type') +@allowed([ + 'Automatic' + 'Direct' + '' +]) +param personalDesktopAssignmentType string = '' + +@description('Optional. Type of load balancer algorithm.') +@allowed([ + 'BreadthFirst' + 'DepthFirst' + 'Persistent' +]) +param loadBalancerType string = 'BreadthFirst' + +@description('Optional. Maximum number of sessions.') +param maxSessionLimit int = 99999 + +@description('Optional. Host Pool RDP properties') +param customRdpProperty string = 'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;' + +@description('Optional. Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation \'ring\' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment.') +param validationEnviroment bool = false + +@description('Optional. The necessary information for adding more VMs to this Host Pool.') +param vmTemplate object = {} + +@description('Optional. Host Pool token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the token will be valid for 8 hours.') +param tokenValidityLength string = 'PT8H' + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The type of preferred application group type, default to Desktop Application Group') +@allowed([ + 'Desktop' + 'None' + 'RailApplications' +]) +param preferredAppGroupType string = 'Desktop' + +@description('Optional. Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs.') +param startVMOnConnect bool = false + +@description('Optional. Validation host pool allows you to test service changes before they are deployed to production.') +param validationEnvironment bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' + 'Connection' + 'HostRegistration' + 'AgentHealthStatus' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' + 'Connection' + 'HostRegistration' + 'AgentHealthStatus' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var tokenExpirationTime = dateTimeAdd(baseTime, tokenValidityLength) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + friendlyName: hostpoolFriendlyName + description: hostpoolDescription + hostPoolType: hostpoolType + customRdpProperty: customRdpProperty + personalDesktopAssignmentType: any(personalDesktopAssignmentType) + preferredAppGroupType: preferredAppGroupType + maxSessionLimit: maxSessionLimit + loadBalancerType: loadBalancerType + validationEnviroment: validationEnviroment + startVMOnConnect: startVMOnConnect + validationEnvironment: validationEnvironment + registrationInfo: { + expirationTime: tokenExpirationTime + token: null + registrationTokenOperation: 'Update' + } + vmTemplate: ((!empty(vmTemplate)) ? null : string(vmTemplate)) + } +} + +resource hostPool_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${hostPool.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: hostPool +} + +resource hostPool_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: hostPool +} + +module hostPool_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-HostPool-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: hostPool.id + } +}] + +@description('The resource ID of the AVD host pool') +output resourceId string = hostPool.id + +@description('The resource group the AVD host pool was deployed into') +output resourceGroupName string = resourceGroup().name + +output hostPoolRestrationInfo object = hostPool.properties.registrationInfo + +@description('The name of the AVD host pool') +output name string = hostPool.name + +@description('The expiration time for the registration token') +output tokenExpirationTime string = dateTimeAdd(baseTime, tokenValidityLength) diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/readme.md b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/readme.md new file mode 100644 index 000000000..455d6783d --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/readme.md @@ -0,0 +1,154 @@ +# AVD Host Pools `[Microsoft.DesktopVirtualization/hostpools]` + +This module deploys an Azure virtual desktop host pool. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/hostPools` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Host Pool | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `customRdpProperty` | string | `'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;'` | | Host Pool RDP properties | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Checkpoint, Error, Management, Connection, HostRegistration, AgentHealthStatus]` | `[Checkpoint, Error, Management, Connection, HostRegistration, AgentHealthStatus]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `hostpoolDescription` | string | `''` | | The description of the Host Pool to be created. | +| `hostpoolFriendlyName` | string | `''` | | The friendly name of the Host Pool to be created. | +| `hostpoolType` | string | `'Pooled'` | `[Personal, Pooled]` | Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled. | +| `loadBalancerType` | string | `'BreadthFirst'` | `[BreadthFirst, DepthFirst, Persistent]` | Type of load balancer algorithm. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxSessionLimit` | int | `99999` | | Maximum number of sessions. | +| `personalDesktopAssignmentType` | string | `''` | `[Automatic, Direct, ]` | Set the type of assignment for a Personal Host Pool type | +| `preferredAppGroupType` | string | `'Desktop'` | `[Desktop, None, RailApplications]` | The type of preferred application group type, default to Desktop Application Group | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `startVMOnConnect` | bool | `False` | | Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `tokenValidityLength` | string | `'PT8H'` | | Host Pool token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the token will be valid for 8 hours. | +| `validationEnviroment` | bool | `False` | | Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation 'ring' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment. | +| `validationEnvironment` | bool | `False` | | Validation host pool allows you to test service changes before they are deployed to production. | +| `vmTemplate` | object | `{object}` | | The necessary information for adding more VMs to this Host Pool. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `vmTemplate` + +The below parameter object is converted to an in-line string when handed over to the resource deployment, since that only takes strings. + +```json +"vmTemplate": { + "value": { + "domain": ".com", + "galleryImageOffer": "office-365", + "galleryImagePublisher": "microsoftwindowsdesktop", + "galleryImageSKU": "19h2-evd-o365pp", + "imageType": "Gallery", + "imageUri": null, + "customImageId": null, + "namePrefix": "AVDv2", + "osDiskType": "StandardSSD_LRS", + "useManagedDisks": true, + "vmSize": { + "id": "Standard_D2s_v3", + "cores": 2, + "ram": 8 + } + } +} +``` + +### Parameter Usage: `customRdpProperty` + +```json +"customRdpProperty": { + "value": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode ID:i:2;" +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD host pool | +| `resourceGroupName` | string | The resource group the AVD host pool was deployed into | +| `resourceId` | string | The resource ID of the AVD host pool | +| `tokenExpirationTime` | string | The expiration time for the registration token | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Hostpools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/hostPools) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/version.json b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/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/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..bc1b6b328 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8') + 'Desktop Virtualization Application Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Host Pool Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc') + 'Desktop Virtualization Host Pool Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Session Host Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408') + 'Desktop Virtualization User Session Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostpools@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(hostPool.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: hostPool +}] diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/.parameters/min.parameters.json new file mode 100644 index 000000000..e576bf370 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdsp-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/deploy.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/deploy.bicep new file mode 100644 index 000000000..3c6a161df --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/deploy.bicep @@ -0,0 +1,156 @@ +@description('Required. Name of the scaling plan') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Friendly Name of the scaling plan') +param friendlyName string = name + +@description('Optional. Description of the scaling plan.') +param scalingplanDescription string = name + +@description('Optional. Timezone to be used for the scaling plan.') +param timeZone string = 'W. Europe Standard Time' + +@allowed([ + 'Pooled' +]) +@description('Optional. The type of hostpool where this scaling plan should be applied.') +param hostPoolType string = 'Pooled' + +@description('Optional. Provide a tag to be used for hosts that should not be affected by the scaling plan.') +param exclusionTag string = '' + +@description('Optional. The schedules related to this scaling plan. If no value is provided a default schedule will be provided.') +param schedules array = [ + { + rampUpStartTime: { + hour: 7 + minute: 0 + } + peakStartTime: { + hour: 9 + minute: 0 + } + rampDownStartTime: { + hour: 18 + minute: 0 + } + offPeakStartTime: { + hour: 20 + minute: 0 + } + name: 'weekdays_schedule' + daysOfWeek: [ + 'Monday' + 'Tuesday' + 'Wednesday' + 'Thursday' + 'Friday' + ] + rampUpLoadBalancingAlgorithm: 'DepthFirst' + rampUpMinimumHostsPct: 20 + rampUpCapacityThresholdPct: 60 + peakLoadBalancingAlgorithm: 'DepthFirst' + rampDownLoadBalancingAlgorithm: 'DepthFirst' + rampDownMinimumHostsPct: 10 + rampDownCapacityThresholdPct: 90 + rampDownForceLogoffUsers: true + rampDownWaitTimeMinutes: 30 + rampDownNotificationMessage: 'You will be logged off in 30 min. Make sure to save your work.' + rampDownStopHostsWhen: 'ZeroSessions' + offPeakLoadBalancingAlgorithm: 'DepthFirst' + } +] + +@description('Optional. An array of references to hostpools.') +param hostPoolReferences array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Autoscale' +]) +param logsToEnable array = [ + 'Autoscale' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource scalingPlan 'Microsoft.DesktopVirtualization/scalingPlans@2021-09-03-preview' = { + name: name + location: location + tags: tags + properties: { + friendlyName: friendlyName + timeZone: timeZone + hostPoolType: hostPoolType + exclusionTag: exclusionTag + schedules: schedules + hostPoolReferences: hostPoolReferences + description: scalingplanDescription + } +} + +resource scalingplan_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${scalingPlan.name}-diagnosticsetting' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: scalingPlan +} + +module scalingplan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Workspace-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: scalingPlan.id + } +}] + +@description('The resource ID of the AVD scaling plan') +output resourceId string = scalingPlan.id + +@description('The resource group the AVD scaling plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD scaling plan') +output name string = scalingPlan.name diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/readme.md b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/readme.md new file mode 100644 index 000000000..9bbb255d1 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/readme.md @@ -0,0 +1,151 @@ +# AVD Scaling Plans `[Microsoft.DesktopVirtualization/scalingPlans]` + +This module deploys an AVD Scaling Plan. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/scalingPlans` | 2021-09-03-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the scaling plan | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `exclusionTag` | string | `''` | | Provide a tag to be used for hosts that should not be affected by the scaling plan. | +| `friendlyName` | string | `[parameters('name')]` | | Friendly Name of the scaling plan | +| `hostPoolReferences` | array | `[]` | | An array of references to hostpools. | +| `hostPoolType` | string | `'Pooled'` | `[Pooled]` | The type of hostpool where this scaling plan should be applied. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `logsToEnable` | array | `[Autoscale]` | `[Autoscale]` | The name of logs that will be streamed. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scalingplanDescription` | string | `[parameters('name')]` | | Description of the scaling plan. | +| `schedules` | array | `[System.Collections.Hashtable]` | | The schedules related to this scaling plan. If no value is provided a default schedule will be provided. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `'W. Europe Standard Time'` | | Timezone to be used for the scaling plan. | + + +### Parameter Usage: `schedules` + +Multiple schedules can be provided as needed. If a schedule is not provided, a default schedule will be created. + +```json +"schedules" : { + "value": [ + { + "rampUpStartTime": { + "hour": 7, + "minute": 0 + }, + "peakStartTime": { + "hour": 9, + "minute": 0 + }, + "rampDownStartTime": { + "hour": 18, + "minute": 0 + }, + "offPeakStartTime": { + "hour": 20, + "minute": 0 + }, + "name": "weekdays_schedule", + "daysOfWeek": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday" + ], + "rampUpLoadBalancingAlgorithm": "DepthFirst", + "rampUpMinimumHostsPct": 20, + "rampUpCapacityThresholdPct": 60, + "peakLoadBalancingAlgorithm": "DepthFirst", + "rampDownLoadBalancingAlgorithm": "DepthFirst", + "rampDownMinimumHostsPct": 10, + "rampDownCapacityThresholdPct": 90, + "rampDownForceLogoffUsers": true, + "rampDownWaitTimeMinutes": 30, + "rampDownNotificationMessage": "You will be logged off in 30 min. Make sure to save your work.", + "rampDownStopHostsWhen": "ZeroSessions", + "offPeakLoadBalancingAlgorithm": "DepthFirst" + }] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD scaling plan | +| `resourceGroupName` | string | The resource group the AVD scaling plan was deployed into | +| `resourceId` | string | The resource ID of the AVD scaling plan | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Scalingplans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-09-03-preview/scalingPlans) diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/version.json b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/version.json new file mode 100644 index 000000000..cfda93cb0 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/scalingplans/version.json @@ -0,0 +1,3 @@ +{ + "version": "0.4" +} \ No newline at end of file diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c51449b59 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/.bicep/nested_rbac.bicep @@ -0,0 +1,58 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Application Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b') + 'Desktop Virtualization Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387') + 'Desktop Virtualization Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868') + 'Desktop Virtualization Workspace Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b') + 'Desktop Virtualization Workspace Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource workspace 'Microsoft.DesktopVirtualization/workspaces@2021-07-12' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(workspace.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: workspace +}] diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json new file mode 100644 index 000000000..7220e4d78 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/.parameters/parameters.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-avdws-x-001" + }, + "location": { + "value": "westeurope" + }, + "appGroupResourceIds": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.DesktopVirtualization/applicationgroups/adp-<>-az-avdag-x-001" + ] + }, + "workspaceFriendlyName": { + "value": "My first AVD Workspace" + }, + "workspaceDescription": { + "value": "This is my first AVD Workspace" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep new file mode 100644 index 000000000..9d6f2c121 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep @@ -0,0 +1,138 @@ +@description('Required. The name of the workspace to be attach to new Application Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Resource IDs fo the existing Application groups this workspace will group together.') +param appGroupResourceIds array = [] + +@description('Optional. The friendly name of the Workspace to be created.') +param workspaceFriendlyName string = '' + +@description('Optional. The description of the Workspace to be created.') +param workspaceDescription string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalIds\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'Checkpoint' + 'Error' + 'Management' + 'Feed' +]) +param diagnosticLogCategoriesToEnable array = [ + 'Checkpoint' + 'Error' + 'Management' + 'Feed' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource workspace 'Microsoft.DesktopVirtualization/workspaces@2021-07-12' = { + name: name + location: location + tags: tags + properties: { + applicationGroupReferences: appGroupResourceIds + description: workspaceDescription + friendlyName: workspaceFriendlyName + } +} + +resource workspace_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${workspace.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: workspace +} + +resource workspace_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: workspace +} + +module workspace_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Workspace-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: workspace.id + } +}] + +@description('The resource ID of the AVD workspace') +output resourceId string = workspace.id + +@description('The resource group the AVD workspace was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the AVD workspace') +output name string = workspace.name diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/readme.md b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/readme.md new file mode 100644 index 000000000..e3285fd88 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/readme.md @@ -0,0 +1,104 @@ +# AVD Workspaces `[Microsoft.DesktopVirtualization/workspaces]` + +This module deploys an Azure virtual desktop workspace. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.DesktopVirtualization/workspaces` | 2021-07-12 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `appGroupResourceIds` | array | Resource IDs fo the existing Application groups this workspace will group together. | +| `name` | string | The name of the workspace to be attach to new Application Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[Checkpoint, Error, Management, Feed]` | `[Checkpoint, Error, Management, Feed]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `workspaceDescription` | string | `''` | | The description of the Workspace to be created. | +| `workspaceFriendlyName` | string | `''` | | The friendly name of the Workspace to be created. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AVD workspace | +| `resourceGroupName` | string | The resource group the AVD workspace was deployed into | +| `resourceId` | string | The resource ID of the AVD workspace | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Workspaces](https://docs.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2021-07-12/workspaces) diff --git a/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/version.json b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/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/carml/1.2.0/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..0e3f625a3 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } +} diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c9e81020f --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/.bicep/nested_rbac.bicep @@ -0,0 +1,62 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Crypto Service Encryption User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') + 'Key Vault Crypto User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Key Vault Secrets User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(keyVault.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: keyVault +}] diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.KeyVault/vaults/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/.parameters/parameters.json b/carml/1.2.0/Microsoft.KeyVault/vaults/.parameters/parameters.json new file mode 100644 index 000000000..bf3331329 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/.parameters/parameters.json @@ -0,0 +1,130 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-kv-x-001" + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "enableRbacAuthorization": { + "value": false + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "vault" + } + ] + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "action": "Allow" + } + ], + "ipRules": [] + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "secrets": { + "value": { + "secureList": [ + { + "name": "secretName", + "value": "secretValue", + "contentType": "Something", + "attributesExp": 1702648632, + "attributesNbf": 10000, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + } + }, + "keys": { + "value": [ + { + "name": "keyName", + "attributesExp": 1702648632, + "attributesNbf": 10000, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + ] + }, + "accessPolicies": { + "value": [ + { + "objectId": "<>", + "permissions": { + "keys": [ + "get", + "list", + "update" + ], + "secrets": [ + "all" + ] + }, + "tenantId": "<>" + }, + { + "objectId": "<>", + "permissions": { + "certificates": [ + "backup", + "create", + "delete" + ], + "secrets": [ + "all" + ] + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep new file mode 100644 index 000000000..97654c373 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. The access policy deployment') +param name string = 'add' + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the access policies assignment') +output name string = policies.name + +@description('The resource ID of the access policies assignment') +output resourceId string = policies.id diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/readme.md b/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/readme.md new file mode 100644 index 000000000..f03526e8c --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/readme.md @@ -0,0 +1,68 @@ +# Key Vault Access Policies `[Microsoft.KeyVault/vaults/accessPolicies]` + +This module deploys key vault access policies. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `accessPolicies` | array | `[]` | An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'add'` | The access policy deployment | + + +### Parameter Usage: `accessPolicies` + +```json +"accessPolicies": { + "value": [ + { + "tenantId": null, // Optional + "applicationId": null, // Optional + "objectId": null, + "permissions": { + "certificates": [ + "All" + ], + "keys": [ + "All" + ], + "secrets": [ + "All" + ] + } + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the access policies assignment | +| `resourceGroupName` | string | The name of the resource group the access policies assignment was created in. | +| `resourceId` | string | The resource ID of the access policies assignment | + +## Template references + +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/version.json b/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/accessPolicies/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/carml/1.2.0/Microsoft.KeyVault/vaults/deploy.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/deploy.bicep new file mode 100644 index 000000000..361f0c20d --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/deploy.bicep @@ -0,0 +1,316 @@ +// ================ // +// Parameters // +// ================ // +@description('Optional. Name of the Key Vault. If no name is provided, then unique name will be created.') +@maxLength(24) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of access policies object') +param accessPolicies array = [] + +@description('Optional. All secrets to create') +@secure() +param secrets object = {} + +@description('Optional. All keys to create') +param keys array = [] + +@description('Optional. Specifies if the vault is enabled for deployment by script or compute') +@allowed([ + true + false +]) +param enableVaultForDeployment bool = true + +@description('Optional. Specifies if the vault is enabled for a template deployment') +@allowed([ + true + false +]) +param enableVaultForTemplateDeployment bool = true + +@description('Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios.') +@allowed([ + true + false +]) +param enableVaultForDiskEncryption bool = true + +@description('Optional. Switch to enable/disable Key Vault\'s soft delete feature.') +param enableSoftDelete bool = true + +@description('Optional. softDelete data retention days. It accepts >=7 and <=90.') +param softDeleteRetentionInDays int = 90 + +@description('Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC.') +param enableRbacAuthorization bool = false + +@description('Optional. The vault\'s create mode to indicate whether the vault need to be recovered or not. - recover or default.') +param createMode string = 'default' + +@description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature.') +param enablePurgeProtection bool = false + +@description('Optional. Specifies the SKU for the vault') +@allowed([ + 'premium' + 'standard' +]) +param vaultSku string = 'premium' + +@description('Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny') +param networkAcls object = {} + +@description('Optional. Property to specify whether the vault will accept traffic from public internet. If set to "disabled" all traffic except private endpoint traffic and that that originates from trusted services will be blocked. This will override the set firewall rules, meaning that even if the firewall rules are present we will not honor the rules.') +@allowed([ + 'enabled' + 'disabled' +]) +param publicNetworkAccess string = 'enabled' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible') +param privateEndpoints array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param baseTime string = utcNow('u') + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'AuditEvent' + 'AzurePolicyEvaluationDetails' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AuditEvent' + 'AzurePolicyEvaluationDetails' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +// =========== // +// Variables // +// =========== // +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var maxNameLength = 24 +var uniquenameUntrim = uniqueString('Key Vault${baseTime}') +var uniquename = (length(uniquenameUntrim) > maxNameLength ? substring(uniquenameUntrim, 0, maxNameLength) : uniquenameUntrim) +var name_var = !empty(name) ? name : uniquename + +var networkAcls_var = { + bypass: !empty(networkAcls) ? networkAcls.bypass : null + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: (!empty(networkAcls) && contains(networkAcls, 'virtualNetworkRules')) ? networkAcls.virtualNetworkRules : [] + ipRules: (!empty(networkAcls) && contains(networkAcls, 'ipRules')) ? networkAcls.ipRules : [] +} + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +var secretList = !empty(secrets) ? secrets.secureList : [] + +// =========== // +// Deployments // +// =========== // +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-11-01-preview' = { + name: name_var + location: location + tags: tags + properties: { + enabledForDeployment: enableVaultForDeployment + enabledForTemplateDeployment: enableVaultForTemplateDeployment + enabledForDiskEncryption: enableVaultForDiskEncryption + enableSoftDelete: enableSoftDelete + softDeleteRetentionInDays: softDeleteRetentionInDays + enableRbacAuthorization: enableRbacAuthorization + createMode: createMode + enablePurgeProtection: enablePurgeProtection ? enablePurgeProtection : null + tenantId: subscription().tenantId + accessPolicies: formattedAccessPolicies + sku: { + name: vaultSku + family: 'A' + } + networkAcls: !empty(networkAcls) ? networkAcls_var : null + publicNetworkAccess: publicNetworkAccess + } +} + +resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${keyVault.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: keyVault +} + +resource keyVault_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: keyVault +} + +module keyVault_accessPolicies 'accessPolicies/deploy.bicep' = if (!empty(accessPolicies)) { + name: '${uniqueString(deployment().name, location)}-KeyVault-AccessPolicies' + params: { + keyVaultName: keyVault.name + accessPolicies: formattedAccessPolicies + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module keyVault_secrets 'secrets/deploy.bicep' = [for (secret, index) in secretList: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Secret-${index}' + params: { + name: secret.name + value: secret.value + keyVaultName: keyVault.name + attributesEnabled: contains(secret, 'attributesEnabled') ? secret.attributesEnabled : true + attributesExp: contains(secret, 'attributesExp') ? secret.attributesExp : -1 + attributesNbf: contains(secret, 'attributesNbf') ? secret.attributesNbf : -1 + contentType: contains(secret, 'contentType') ? secret.contentType : '' + tags: contains(secret, 'tags') ? secret.tags : {} + roleAssignments: contains(secret, 'roleAssignments') ? secret.roleAssignments : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module keyVault_keys 'keys/deploy.bicep' = [for (key, index) in keys: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Key-${index}' + params: { + name: key.name + keyVaultName: keyVault.name + attributesEnabled: contains(key, 'attributesEnabled') ? key.attributesEnabled : true + attributesExp: contains(key, 'attributesExp') ? key.attributesExp : -1 + attributesNbf: contains(key, 'attributesNbf') ? key.attributesNbf : -1 + curveName: contains(key, 'curveName') ? key.curveName : 'P-256' + keyOps: contains(key, 'keyOps') ? key.keyOps : [] + keySize: contains(key, 'keySize') ? key.keySize : -1 + kty: contains(key, 'kty') ? key.kty : 'EC' + tags: contains(key, 'tags') ? key.tags : {} + roleAssignments: contains(key, 'roleAssignments') ? key.roleAssignments : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module keyVault_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: { + name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: keyVault.id + privateEndpointVnetLocation: empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module keyVault_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-KeyVault-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: keyVault.id + } +}] + +// =========== // +// Outputs // +// =========== // +@description('The resource ID of the key vault.') +output resourceId string = keyVault.id + +@description('The name of the resource group the key vault was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the key vault.') +output name string = keyVault.name + +@description('The URI of the key vault.') +output uri string = keyVault.properties.vaultUri diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..98d77676a --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Crypto Service Encryption User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') + 'Key Vault Crypto User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource key 'Microsoft.KeyVault/vaults/keys@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(key.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: key +}] diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/keys/deploy.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/deploy.bicep new file mode 100644 index 000000000..6b64e910a --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/deploy.bicep @@ -0,0 +1,109 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Required. The name of the key') +param name string + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Determines whether the object is enabled.') +param attributesEnabled bool = true + +@description('Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible.') +param attributesExp int = -1 + +@description('Optional. Not before date in seconds since 1970-01-01T00:00:00Z.') +param attributesNbf int = -1 + +@description('Optional. The elliptic curve name.') +@allowed([ + 'P-256' + 'P-256K' + 'P-384' + 'P-521' +]) +param curveName string = 'P-256' + +@description('Optional. Array of JsonWebKeyOperation') +@allowed([ + 'decrypt' + 'encrypt' + 'import' + 'sign' + 'unwrapKey' + 'verify' + 'wrapKey' +]) +param keyOps array = [] + +@description('Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA.') +param keySize int = -1 + +@description('Optional. The type of the key.') +@allowed([ + 'EC' + 'EC-HSM' + 'RSA' + 'RSA-HSM' +]) +param kty string = 'EC' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource key 'Microsoft.KeyVault/vaults/keys@2019-09-01' = { + name: name + parent: keyVault + tags: tags + properties: { + attributes: { + enabled: attributesEnabled + exp: attributesExp != -1 ? attributesExp : null + nbf: attributesNbf != -1 ? attributesNbf : null + } + curveName: curveName + keyOps: keyOps + keySize: keySize != -1 ? keySize : null + kty: kty + } +} + +module key_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: key.id + } +}] + +@description('The name of the key.') +output name string = key.name + +@description('The resource ID of the key.') +output resourceId string = key.id + +@description('The name of the resource group the key was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/keys/readme.md b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/readme.md new file mode 100644 index 000000000..a668a8dce --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/readme.md @@ -0,0 +1,96 @@ +# Key Vault Key `[Microsoft.KeyVault/vaults/keys]` + +This module deploys a key vault key. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.KeyVault/vaults/keys` | 2019-09-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault | +| `name` | string | The name of the key | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `attributesEnabled` | bool | `True` | | Determines whether the object is enabled. | +| `attributesExp` | int | `-1` | | Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible. | +| `attributesNbf` | int | `-1` | | Not before date in seconds since 1970-01-01T00:00:00Z. | +| `curveName` | string | `'P-256'` | `[P-256, P-256K, P-384, P-521]` | The elliptic curve name. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `keyOps` | array | `[]` | `[decrypt, encrypt, import, sign, unwrapKey, verify, wrapKey]` | Array of JsonWebKeyOperation | +| `keySize` | int | `-1` | | The key size in bits. For example: 2048, 3072, or 4096 for RSA. | +| `kty` | string | `'EC'` | `[EC, EC-HSM, RSA, RSA-HSM]` | The type of the key. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the key. | +| `resourceGroupName` | string | The name of the resource group the key was created in. | +| `resourceId` | string | The resource ID of the key. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/keys) diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/keys/version.json b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/keys/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/carml/1.2.0/Microsoft.KeyVault/vaults/readme.md b/carml/1.2.0/Microsoft.KeyVault/vaults/readme.md new file mode 100644 index 000000000..7930d560c --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/readme.md @@ -0,0 +1,215 @@ +# Key Vaults `[Microsoft.KeyVault/vaults]` + +This module deploys a key vault and its child resources. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.KeyVault/vaults` | 2021-11-01-preview | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | +| `Microsoft.KeyVault/vaults/keys` | 2019-09-01 | +| `Microsoft.KeyVault/vaults/secrets` | 2019-09-01 | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `accessPolicies` | _[accessPolicies](accessPolicies/readme.md)_ array | `[]` | | Array of access policies object | +| `createMode` | string | `'default'` | | The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogCategoriesToEnable` | array | `[AuditEvent, AzurePolicyEvaluationDetails]` | `[AuditEvent, AzurePolicyEvaluationDetails]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enablePurgeProtection` | bool | `False` | | Provide 'true' to enable Key Vault's purge protection feature. | +| `enableRbacAuthorization` | bool | `False` | | Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC. | +| `enableSoftDelete` | bool | `True` | | Switch to enable/disable Key Vault's soft delete feature. | +| `enableVaultForDeployment` | bool | `True` | `[True, False]` | Specifies if the vault is enabled for deployment by script or compute | +| `enableVaultForDiskEncryption` | bool | `True` | `[True, False]` | Specifies if the azure platform has access to the vault for enabling disk encryption scenarios. | +| `enableVaultForTemplateDeployment` | bool | `True` | `[True, False]` | Specifies if the vault is enabled for a template deployment | +| `keys` | _[keys](keys/readme.md)_ array | `[]` | | All keys to create | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `name` | string | `''` | | Name of the Key Vault. If no name is provided, then unique name will be created. | +| `networkAcls` | object | `{object}` | | Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible | +| `publicNetworkAccess` | string | `'enabled'` | `[enabled, disabled]` | Property to specify whether the vault will accept traffic from public internet. If set to "disabled" all traffic except private endpoint traffic and that that originates from trusted services will be blocked. This will override the set firewall rules, meaning that even if the firewall rules are present we will not honor the rules. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `secrets` | secureObject | `{object}` | | All secrets to create | +| `softDeleteRetentionInDays` | int | `90` | | softDelete data retention days. It accepts >=7 and <=90. | +| `tags` | object | `{object}` | | Resource tags. | +| `vaultSku` | string | `'premium'` | `[premium, standard]` | Specifies the SKU for the vault | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a SAS token to access the modules. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001" + } + ], + "ipRules": [] + } +} +``` + +### Parameter Usage: `vNetId` + +```json +"vNetId": { + "value": "/subscriptions/00000000/resourceGroups/resourceGroup" +} +``` + +### Parameter Usage: `accessPolicies` + +```json +"accessPolicies": { + "value": [ + { + "tenantId": null, // Optional + "applicationId": null, // Optional + "objectId": null, + "permissions": { + "certificates": [ + "All" + ], + "keys": [ + "All" + ], + "secrets": [ + "All" + ] + } + } + ] +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the key vault. | +| `resourceGroupName` | string | The name of the resource group the key vault was created in. | +| `resourceId` | string | The resource ID of the key vault. | +| `uri` | string | The URI of the key vault. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-11-01-preview/vaults) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) +- [Vaults/Keys](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/keys) +- [Vaults/Secrets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/secrets) diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4c12c17bd --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Key Vault Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + 'Key Vault Certificates Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Key Vault Crypto Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603') + 'Key Vault Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2') + 'Key Vault Secrets Officer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') + 'Key Vault Secrets User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource secret 'Microsoft.KeyVault/vaults/secrets@2021-06-01-preview' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(secret.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: secret +}] diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/deploy.bicep b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/deploy.bicep new file mode 100644 index 000000000..1666885b3 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/deploy.bicep @@ -0,0 +1,82 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Required. The name of the secret') +param name string + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Determines whether the object is enabled.') +param attributesEnabled bool = true + +@description('Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible.') +param attributesExp int = -1 + +@description('Optional. Not before date in seconds since 1970-01-01T00:00:00Z.') +param attributesNbf int = -1 + +@description('Optional. The content type of the secret.') +@secure() +param contentType string = '' + +@description('Required. The value of the secret. NOTE: "value" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets.') +@secure() +param value string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource secret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = { + name: name + parent: keyVault + tags: tags + properties: { + contentType: contentType + attributes: { + enabled: attributesEnabled + exp: attributesExp != -1 ? attributesExp : null + nbf: attributesNbf != -1 ? attributesNbf : null + } + value: value + } +} + +module secret_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: secret.id + } +}] + +@description('The name of the secret.') +output name string = secret.name + +@description('The resource ID of the secret.') +output resourceId string = secret.id + +@description('The name of the resource group the secret was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/readme.md b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/readme.md new file mode 100644 index 000000000..45c02db41 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/readme.md @@ -0,0 +1,94 @@ +# Key Vault Secret `[Microsoft.KeyVault/vaults/secrets]` + +This module deploys a key vault secret. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.KeyVault/vaults/secrets` | 2019-09-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `keyVaultName` | string | The name of the key vault | +| `name` | string | The name of the secret | +| `value` | secureString | The value of the secret. NOTE: "value" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `attributesEnabled` | bool | `True` | Determines whether the object is enabled. | +| `attributesExp` | int | `-1` | Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible. | +| `attributesNbf` | int | `-1` | Not before date in seconds since 1970-01-01T00:00:00Z. | +| `contentType` | secureString | `''` | The content type of the secret. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | Resource tags. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the secret. | +| `resourceGroupName` | string | The name of the resource group the secret was created in. | +| `resourceId` | string | The resource ID of the secret. | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vaults/Secrets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/secrets) diff --git a/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/version.json b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/secrets/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/carml/1.2.0/Microsoft.KeyVault/vaults/version.json b/carml/1.2.0/Microsoft.KeyVault/vaults/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.KeyVault/vaults/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/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..cbb3862c2 --- /dev/null +++ b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource userMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(userMsi.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: userMsi +}] diff --git a/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json new file mode 100644 index 000000000..141d57730 --- /dev/null +++ b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-msi-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep new file mode 100644 index 000000000..204da36b7 --- /dev/null +++ b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep @@ -0,0 +1,72 @@ +@description('Optional. Name of the User Assigned Identity.') +param name string = guid(resourceGroup().id) + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource userMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: name + location: location + tags: tags +} + +resource userMsi_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${userMsi.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: userMsi +} + +module userMsi_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-UserMSI-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: userMsi.id + } +}] + +@description('The name of the user assigned identity') +output name string = userMsi.name + +@description('The resource ID of the user assigned identity') +output resourceId string = userMsi.id + +@description('The principal ID of the user assigned identity') +output principalId string = userMsi.properties.principalId + +@description('The resource group the user assigned identity was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md new file mode 100644 index 000000000..dffc0d77a --- /dev/null +++ b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md @@ -0,0 +1,89 @@ +# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` + +This module deploys a user assigned identity. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.ManagedIdentity/userAssignedIdentities` | 2018-11-30 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `name` | string | `[guid(resourceGroup().id)]` | | Name of the User Assigned Identity. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the user assigned identity | +| `principalId` | string | The principal ID of the user assigned identity | +| `resourceGroupName` | string | The resource group the user assigned identity was deployed into | +| `resourceId` | string | The resource ID of the user assigned identity | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Userassignedidentities](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2018-11-30/userAssignedIdentities) diff --git a/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/version.json b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/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/carml/1.2.0/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..a7bda4c41 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource applicationGateway 'Microsoft.Network/applicationGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(applicationGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: applicationGateway +}] diff --git a/carml/1.2.0/Microsoft.Network/applicationGateways/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/applicationGateways/.parameters/parameters.json new file mode 100644 index 000000000..e0a8603a8 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationGateways/.parameters/parameters.json @@ -0,0 +1,364 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-apgw-x-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "webApplicationFirewallConfiguration": { + "value": { + "enabled": true, + "firewallMode": "Detection", + "ruleSetType": "OWASP", + "ruleSetVersion": "3.0", + "disabledRuleGroups": [], + "requestBodyCheck": true, + "maxRequestBodySizeInKb": 128, + "fileUploadLimitInMb": 100 + } + }, + "enableHttp2": { + "value": true + }, + "backendAddressPools": { + "value": [ + { + "name": "appServiceBackendPool", + "properties": { + "backendAddresses": [ + { + "fqdn": "aghapp.azurewebsites.net" + } + ] + } + }, + { + "name": "privateVmBackendPool", + "properties": { + "backendAddresses": [ + { + "ipAddress": "10.0.0.4" + } + ] + } + } + ] + }, + "backendHttpSettingsCollection": { + "value": [ + { + "name": "appServiceBackendHttpsSetting", + "properties": { + "port": 443, + "protocol": "Https", + "cookieBasedAffinity": "Disabled", + "pickHostNameFromBackendAddress": true, + "requestTimeout": 30 + } + }, + { + "name": "privateVmHttpSetting", + "properties": { + "port": 80, + "protocol": "Http", + "cookieBasedAffinity": "Disabled", + "pickHostNameFromBackendAddress": false, + "requestTimeout": 30, + "probe": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/probes/privateVmHttpSettingProbe" + } + } + } + ] + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "private", + "properties": { + "privateIPAddress": "10.0.8.6", + "privateIPAllocationMethod": "Static", + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-007" + } + } + }, + { + "name": "public", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-apgw" + } + } + } + ] + }, + "frontendPorts": { + "value": [ + { + "name": "port443", + "properties": { + "port": 443 + } + }, + { + "name": "port4433", + "properties": { + "port": 4433 + } + }, + { + "name": "port80", + "properties": { + "port": 80 + } + }, + { + "name": "port8080", + "properties": { + "port": 8080 + } + } + ] + }, + "httpListeners": { + "value": [ + { + "name": "public443", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/public" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port443" + }, + "sslCertificate": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/sslCertificates/<>-az-apgw-x-001-ssl-certificate" + }, + "protocol": "https", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "private4433", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/private" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port4433" + }, + "sslCertificate": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/sslCertificates/<>-az-apgw-x-001-ssl-certificate" + }, + "protocol": "https", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "httpRedirect80", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/public" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port80" + }, + "protocol": "Http", + "hostNames": [], + "requireServerNameIndication": false + } + }, + { + "name": "httpRedirect8080", + "properties": { + "frontendIPConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendIPConfigurations/private" + }, + "frontendPort": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/frontendPorts/port8080" + }, + "protocol": "Http", + "hostNames": [], + "requireServerNameIndication": false + } + } + ] + }, + "gatewayIPConfigurations": { + "value": [ + { + "name": "apw-ip-configuration", + "properties": { + "subnet": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-007" + } + } + } + ] + }, + "probes": { + "value": [ + { + "name": "privateVmHttpSettingProbe", + "properties": { + "protocol": "Http", + "host": "10.0.0.4", + "path": "/", + "interval": 60, + "timeout": 15, + "unhealthyThreshold": 5, + "pickHostNameFromBackendHttpSettings": false, + "minServers": 3, + "match": { + "statusCodes": [ + "200", + "401" + ] + } + } + } + ] + }, + "redirectConfigurations": { + "value": [ + { + "name": "httpRedirect80", + "properties": { + "redirectType": "Permanent", + "targetListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/public443" + }, + "includePath": true, + "includeQueryString": true, + "requestRoutingRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/requestRoutingRules/httpRedirect80-public443" + } + ] + } + }, + { + "name": "httpRedirect8080", + "properties": { + "redirectType": "Permanent", + "targetListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/private4433" + }, + "includePath": true, + "includeQueryString": true, + "requestRoutingRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/requestRoutingRules/httpRedirect8080-private4433" + } + ] + } + } + ] + }, + "requestRoutingRules": { + "value": [ + { + "name": "public443-appServiceBackendHttpsSetting-appServiceBackendHttpsSetting", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/public443" + }, + "backendAddressPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendAddressPools/appServiceBackendPool" + }, + "backendHttpSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendHttpSettingsCollection/appServiceBackendHttpsSetting" + } + } + }, + { + "name": "private4433-privateVmHttpSetting-privateVmHttpSetting", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/private4433" + }, + "backendAddressPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendAddressPools/privateVmBackendPool" + }, + "backendHttpSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/backendHttpSettingsCollection/privateVmHttpSetting" + } + } + }, + { + "name": "httpRedirect80-public443", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/httpRedirect80" + }, + "redirectConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/redirectConfigurations/httpRedirect80" + } + } + }, + { + "name": "httpRedirect8080-private4433", + "properties": { + "ruleType": "Basic", + "httpListener": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/httpListeners/httpRedirect8080" + }, + "redirectConfiguration": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationGateways/<>-az-apgw-x-001/redirectConfigurations/httpRedirect8080" + } + } + } + ] + }, + "sku": { + "value": "WAF_v2" + }, + "sslCertificates": { + "value": [ + { + "name": "<>-az-apgw-x-001-ssl-certificate", + "properties": { + "keyVaultSecretId": "https://adp-<>-az-kv-x-001.vault.azure.net/secrets/applicationGatewaySslCertificate02/40b9b1a7a69e48cfa1e36f24b97b8799" + } + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/applicationGateways/deploy.bicep b/carml/1.2.0/Microsoft.Network/applicationGateways/deploy.bicep new file mode 100644 index 000000000..c94b24d39 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationGateways/deploy.bicep @@ -0,0 +1,363 @@ +@description('Required. Name of the Application Gateway.') +@maxLength(24) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Authentication certificates of the application gateway resource.') +param authenticationCertificates array = [] + +@description('Optional. Upper bound on number of Application Gateway capacity.') +param autoscaleMaxCapacity int = -1 + +@description('Optional. Lower bound on number of Application Gateway capacity.') +param autoscaleMinCapacity int = -1 + +@description('Optional. Backend address pool of the application gateway resource.') +param backendAddressPools array = [] + +@description('Optional. Backend http settings of the application gateway resource.') +param backendHttpSettingsCollection array = [] + +@description('Optional. Custom error configurations of the application gateway resource.') +param customErrorConfigurations array = [] + +@description('Optional. Whether FIPS is enabled on the application gateway resource.') +param enableFips bool = false + +@description('Optional. Whether HTTP2 is enabled on the application gateway resource.') +param enableHttp2 bool = false + +@description('Optional. The resource ID of an associated firewall policy.') +param firewallPolicyId string = '' + +@description('Optional. Frontend IP addresses of the application gateway resource.') +param frontendIPConfigurations array = [] + +@description('Optional. Frontend ports of the application gateway resource.') +param frontendPorts array = [] + +@description('Optional. Subnets of the application gateway resource.') +param gatewayIPConfigurations array = [] + +@description('Optional. Enable request buffering.') +param enableRequestBuffering bool = false + +@description('Optional. Enable response buffering.') +param enableResponseBuffering bool = false + +@description('Optional. Http listeners of the application gateway resource.') +param httpListeners array = [] + +@description('Optional. Load distribution policies of the application gateway resource.') +param loadDistributionPolicies array = [] + +@description('Optional. PrivateLink configurations on application gateway.') +param privateLinkConfigurations array = [] + +@description('Optional. Probes of the application gateway resource.') +param probes array = [] + +@description('Optional. Redirect configurations of the application gateway resource.') +param redirectConfigurations array = [] + +@description('Optional. Request routing rules of the application gateway resource.') +param requestRoutingRules array = [] + +@description('Optional. Rewrite rules for the application gateway resource. ') +param rewriteRuleSets array = [] + +@description('Optional. The name of the SKU for the Application Gateway.') +@allowed([ + 'Standard_Small' + 'Standard_Medium' + 'Standard_Large' + 'WAF_Medium' + 'WAF_Large' + 'Standard_v2' + 'WAF_v2' +]) +param sku string = 'WAF_Medium' + +@description('Optional. The number of Application instances to be configured.') +@minValue(1) +@maxValue(10) +param capacity int = 2 + +@description('Optional. SSL certificates of the application gateway resource.') +param sslCertificates array = [] + +@description('Optional. Ssl cipher suites to be enabled in the specified order to application gateway.') +@allowed([ + 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256' + 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA' + 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256' + 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA' + 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA' + 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA' + 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256' + 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256' + 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA' + 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384' + 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA' + 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256' + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA' + 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_RSA_WITH_3DES_EDE_CBC_SHA' + 'TLS_RSA_WITH_AES_128_CBC_SHA' + 'TLS_RSA_WITH_AES_128_CBC_SHA256' + 'TLS_RSA_WITH_AES_128_GCM_SHA256' + 'TLS_RSA_WITH_AES_256_CBC_SHA' + 'TLS_RSA_WITH_AES_256_CBC_SHA256' + 'TLS_RSA_WITH_AES_256_GCM_SHA384' +]) +param sslPolicyCipherSuites array = [ + 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384' + 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256' +] + +@description('Optional. Ssl protocol enums.') +@allowed([ + 'TLSv1_0' + 'TLSv1_1' + 'TLSv1_2' +]) +param sslPolicyMinProtocolVersion string = 'TLSv1_2' + +@description('Optional. Ssl predefined policy name enums.') +@allowed([ + 'AppGwSslPolicy20150501' + 'AppGwSslPolicy20170401' + 'AppGwSslPolicy20170401S' + '' +]) +param sslPolicyName string = '' + +@description('Optional. Type of Ssl Policy.') +@allowed([ + 'Custom' + 'Predefined' +]) +param sslPolicyType string = 'Custom' + +@description('Optional. SSL profiles of the application gateway resource.') +param sslProfiles array = [] + +@description('Optional. Trusted client certificates of the application gateway resource.') +param trustedClientCertificates array = [] + +@description('Optional. Trusted Root certificates of the application gateway resource.') +param trustedRootCertificates array = [] + +@description('Optional. URL path map of the application gateway resource.') +param urlPathMaps array = [] + +@description('Optional. Application gateway web application firewall configuration.') +param webApplicationFirewallConfiguration object = {} + +@description('Optional. A list of availability zones denoting where the resource needs to come from.') +param zones array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ApplicationGatewayAccessLog' + 'ApplicationGatewayPerformanceLog' + 'ApplicationGatewayFirewallLog' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ApplicationGatewayAccessLog' + 'ApplicationGatewayPerformanceLog' + 'ApplicationGatewayFirewallLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource applicationGateway 'Microsoft.Network/applicationGateways@2021-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: union({ + authenticationCertificates: authenticationCertificates + autoscaleConfiguration: autoscaleMaxCapacity > 0 && autoscaleMinCapacity > 0 ? { + maxCapacity: autoscaleMaxCapacity + minCapacity: autoscaleMinCapacity + } : null + backendAddressPools: backendAddressPools + backendHttpSettingsCollection: backendHttpSettingsCollection + customErrorConfigurations: customErrorConfigurations + enableHttp2: enableHttp2 + firewallPolicy: !empty(firewallPolicyId) ? { + id: firewallPolicyId + } : null + forceFirewallPolicyAssociation: !empty(firewallPolicyId) + frontendIPConfigurations: frontendIPConfigurations + frontendPorts: frontendPorts + gatewayIPConfigurations: gatewayIPConfigurations + globalConfiguration: { + enableRequestBuffering: enableRequestBuffering + enableResponseBuffering: enableResponseBuffering + } + httpListeners: httpListeners + loadDistributionPolicies: loadDistributionPolicies + privateLinkConfigurations: privateLinkConfigurations + probes: probes + redirectConfigurations: redirectConfigurations + requestRoutingRules: requestRoutingRules + rewriteRuleSets: rewriteRuleSets + sku: { + name: sku + tier: endsWith(sku, 'v2') ? sku : substring(sku, 0, indexOf(sku, '_')) + capacity: autoscaleMaxCapacity > 0 && autoscaleMinCapacity > 0 ? null : capacity + } + sslCertificates: sslCertificates + sslPolicy: { + cipherSuites: sslPolicyCipherSuites + minProtocolVersion: sslPolicyMinProtocolVersion + policyName: empty(sslPolicyName) ? null : sslPolicyName + policyType: sslPolicyType + } + sslProfiles: sslProfiles + trustedClientCertificates: trustedClientCertificates + trustedRootCertificates: trustedRootCertificates + urlPathMaps: urlPathMaps + webApplicationFirewallConfiguration: webApplicationFirewallConfiguration + }, (enableFips ? { + enableFips: enableFips + } : {}), {}) + zones: zones +} + +resource applicationGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${applicationGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: applicationGateway +} + +resource applicationGateway_diagnosticSettingName 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId + workspaceId: empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId + eventHubAuthorizationRuleId: empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId + eventHubName: empty(diagnosticEventHubName) ? null : diagnosticEventHubName + metrics: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsMetrics + logs: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsLogs + } + scope: applicationGateway +} + +module applicationGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: applicationGateway.id + } +}] + +@description('The name of the application gateway') +output name string = applicationGateway.name + +@description('The resource ID of the application gateway') +output resourceId string = applicationGateway.id + +@description('The resource group the application gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/applicationGateways/readme.md b/carml/1.2.0/Microsoft.Network/applicationGateways/readme.md new file mode 100644 index 000000000..cf11dd4a7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationGateways/readme.md @@ -0,0 +1,687 @@ +# Network Application Gateways `[Microsoft.Network/applicationGateways]` + +This module deploys Network ApplicationGateways. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/applicationGateways` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Application Gateway. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `authenticationCertificates` | array | `[]` | | Authentication certificates of the application gateway resource. | +| `autoscaleMaxCapacity` | int | `-1` | | Upper bound on number of Application Gateway capacity. | +| `autoscaleMinCapacity` | int | `-1` | | Lower bound on number of Application Gateway capacity. | +| `backendAddressPools` | array | `[]` | | Backend address pool of the application gateway resource. | +| `backendHttpSettingsCollection` | array | `[]` | | Backend http settings of the application gateway resource. | +| `capacity` | int | `2` | | The number of Application instances to be configured. | +| `customErrorConfigurations` | array | `[]` | | Custom error configurations of the application gateway resource. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogCategoriesToEnable` | array | `[ApplicationGatewayAccessLog, ApplicationGatewayPerformanceLog, ApplicationGatewayFirewallLog]` | `[ApplicationGatewayAccessLog, ApplicationGatewayPerformanceLog, ApplicationGatewayFirewallLog]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableFips` | bool | `False` | | Whether FIPS is enabled on the application gateway resource. | +| `enableHttp2` | bool | `False` | | Whether HTTP2 is enabled on the application gateway resource. | +| `enableRequestBuffering` | bool | `False` | | Enable request buffering. | +| `enableResponseBuffering` | bool | `False` | | Enable response buffering. | +| `firewallPolicyId` | string | `''` | | The resource ID of an associated firewall policy. | +| `frontendIPConfigurations` | array | `[]` | | Frontend IP addresses of the application gateway resource. | +| `frontendPorts` | array | `[]` | | Frontend ports of the application gateway resource. | +| `gatewayIPConfigurations` | array | `[]` | | Subnets of the application gateway resource. | +| `httpListeners` | array | `[]` | | Http listeners of the application gateway resource. | +| `loadDistributionPolicies` | array | `[]` | | Load distribution policies of the application gateway resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateLinkConfigurations` | array | `[]` | | PrivateLink configurations on application gateway. | +| `probes` | array | `[]` | | Probes of the application gateway resource. | +| `redirectConfigurations` | array | `[]` | | Redirect configurations of the application gateway resource. | +| `requestRoutingRules` | array | `[]` | | Request routing rules of the application gateway resource. | +| `rewriteRuleSets` | array | `[]` | | Rewrite rules for the application gateway resource. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sku` | string | `'WAF_Medium'` | `[Standard_Small, Standard_Medium, Standard_Large, WAF_Medium, WAF_Large, Standard_v2, WAF_v2]` | The name of the SKU for the Application Gateway. | +| `sslCertificates` | array | `[]` | | SSL certificates of the application gateway resource. | +| `sslPolicyCipherSuites` | array | `[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]` | `[TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384]` | Ssl cipher suites to be enabled in the specified order to application gateway. | +| `sslPolicyMinProtocolVersion` | string | `'TLSv1_2'` | `[TLSv1_0, TLSv1_1, TLSv1_2]` | Ssl protocol enums. | +| `sslPolicyName` | string | `''` | `[AppGwSslPolicy20150501, AppGwSslPolicy20170401, AppGwSslPolicy20170401S, ]` | Ssl predefined policy name enums. | +| `sslPolicyType` | string | `'Custom'` | `[Custom, Predefined]` | Type of Ssl Policy. | +| `sslProfiles` | array | `[]` | | SSL profiles of the application gateway resource. | +| `tags` | object | `{object}` | | Resource tags. | +| `trustedClientCertificates` | array | `[]` | | Trusted client certificates of the application gateway resource. | +| `trustedRootCertificates` | array | `[]` | | Trusted Root certificates of the application gateway resource. | +| `urlPathMaps` | array | `[]` | | URL path map of the application gateway resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `webApplicationFirewallConfiguration` | object | `{object}` | | Application gateway web application firewall configuration. | +| `zones` | array | `[]` | | A list of availability zones denoting where the resource needs to come from. | + + +### Parameter Usage: `authenticationCertificates` + +```json +"authenticationCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string" + } + } + ] +} +``` + +### Parameter Usage: `backendAddressPools` + +```json +"backendAddressPools": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddresses": [ + { + "fqdn": "string", + "ipAddress": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `backendHttpSettingsCollection` + +```json +"backendHttpSettingsCollection": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "affinityCookieName": "string", + "authenticationCertificates": [ + { + "id": "string" + } + ], + "connectionDraining": { + "drainTimeoutInSec": "int", + "enabled": "bool" + }, + "cookieBasedAffinity": "string", + "hostName": "string", + "path": "string", + "pickHostNameFromBackendAddress": "bool", + "port": "int", + "probe": { + "id": "string" + }, + "probeEnabled": "bool", + "protocol": "string", + "requestTimeout": "int", + "trustedRootCertificates": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `customErrorConfigurations` + +```json +"customErrorConfigurations": { + "value": [ + { + "customErrorPageUrl": "string", + "statusCode": "string" + } + ] +} +``` + +### Parameter Usage: `frontendIPConfigurations` + +```json +"frontendIPConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "privateIPAddress": "string", + "privateIPAllocationMethod": "string", + "privateLinkConfiguration": { + "id": "string" + }, + "publicIPAddress": { + "id": "string" + }, + "subnet": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `frontendPorts` + +```json +"frontendPorts": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "port": "int" + } + } + ] +} +``` + +### Parameter Usage: `gatewayIPConfigurations` + +```json +"gatewayIPConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "subnet": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `httpListeners` + +```json +"httpListeners": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "customErrorConfigurations": [ + { + "customErrorPageUrl": "string", + "statusCode": "string" + } + ], + "firewallPolicy": { + "id": "string" + }, + "frontendIPConfiguration": { + "id": "string" + }, + "frontendPort": { + "id": "string" + }, + "hostName": "string", + "hostNames": [ "string" ], + "protocol": "string", + "requireServerNameIndication": "bool", + "sslCertificate": { + "id": "string" + }, + "sslProfile": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `loadDistributionPolicies` + +```json +"loadDistributionPolicies": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "loadDistributionAlgorithm": "string", + "loadDistributionTargets": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "weightPerServer": "int" + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `privateLinkConfigurations` + +```json +"privateLinkConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "ipConfigurations": [ + { + "id": "string", + "name": "string", + "properties": { + "primary": "bool", + "privateIPAddress": "string", + "privateIPAllocationMethod": "string", + "subnet": { + "id": "string" + } + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `probes` + +```json +"probes": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "host": "string", + "interval": "int", + "match": { + "body": "string", + "statusCodes": [ "string" ] + }, + "minServers": "int", + "path": "string", + "pickHostNameFromBackendHttpSettings": "bool", + "port": "int", + "protocol": "string", + "timeout": "int", + "unhealthyThreshold": "int" + } + } + ] +} +``` + +### Parameter Usage: `redirectConfigurations` + +```json +"redirectConfigurations": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "includePath": "bool", + "includeQueryString": "bool", + "pathRules": [ + { + "id": "string" + } + ], + "redirectType": "string", + "requestRoutingRules": [ + { + "id": "string" + } + ], + "targetListener": { + "id": "string" + }, + "targetUrl": "string", + "urlPathMaps": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `requestRoutingRules` + +```json +"requestRoutingRules": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "backendHttpSettings": { + "id": "string" + }, + "httpListener": { + "id": "string" + }, + "loadDistributionPolicy": { + "id": "string" + }, + "priority": "int", + "redirectConfiguration": { + "id": "string" + }, + "rewriteRuleSet": { + "id": "string" + }, + "ruleType": "string", + "urlPathMap": { + "id": "string" + } + } + } + ] +} +``` + +### Parameter Usage: `rewriteRuleSets` + +```json +"rewriteRuleSets": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "rewriteRules": [ + { + "actionSet": { + "requestHeaderConfigurations": [ + { + "headerName": "string", + "headerValue": "string" + } + ], + "responseHeaderConfigurations": [ + { + "headerName": "string", + "headerValue": "string" + } + ], + "urlConfiguration": { + "modifiedPath": "string", + "modifiedQueryString": "string", + "reroute": "bool" + } + }, + "conditions": [ + { + "ignoreCase": "bool", + "negate": "bool", + "pattern": "string", + "variable": "string" + } + ], + "name": "string", + "ruleSequence": "int" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `sslCertificates` + +```json +"sslCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string", + "keyVaultSecretId": "string", + "password": "string" + } + } + ] +} +``` + +### Parameter Usage: `sslProfiles` + +```json +"sslProfiles": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "clientAuthConfiguration": { + "verifyClientCertIssuerDN": "bool" + }, + "sslPolicy": { + "cipherSuites": [ "string" ], + "disabledSslProtocols": [ "string" ], + "minProtocolVersion": "string", + "policyName": "string", + "policyType": "string" + }, + "trustedClientCertificates": [ + { + "id": "string" + } + ] + } + } + ] +} +``` + +### Parameter Usage: `trustedClientCertificates` + +```json +"trustedClientCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string" + } + } + ] +} +``` + +### Parameter Usage: `trustedRootCertificates` + +```json +"trustedRootCertificates": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "data": "string", + "keyVaultSecretId": "string" + } + } + ] +} +``` + +### Parameter Usage: `urlPathMaps` + +```json +"urlPathMaps": { + "value": [ + { + "id": "string", + "name": "string", + "properties": { + "defaultBackendAddressPool": { + "id": "string" + }, + "defaultBackendHttpSettings": { + "id": "string" + }, + "defaultLoadDistributionPolicy": { + "id": "string" + }, + "defaultRedirectConfiguration": { + "id": "string" + }, + "defaultRewriteRuleSet": { + "id": "string" + }, + "pathRules": [ + { + "id": "string", + "name": "string", + "properties": { + "backendAddressPool": { + "id": "string" + }, + "backendHttpSettings": { + "id": "string" + }, + "firewallPolicy": { + "id": "string" + }, + "loadDistributionPolicy": { + "id": "string" + }, + "paths": [ "string" ], + "redirectConfiguration": { + "id": "string" + }, + "rewriteRuleSet": { + "id": "string" + } + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application gateway | +| `resourceGroupName` | string | The resource group the application gateway was deployed into | +| `resourceId` | string | The resource ID of the application gateway | + +## Template references + +- [Applicationgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/applicationGateways) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/applicationGateways/version.json b/carml/1.2.0/Microsoft.Network/applicationGateways/version.json new file mode 100644 index 000000000..badc0a228 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationGateways/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.5" +} diff --git a/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..322247562 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(applicationSecurityGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: applicationSecurityGroup +}] diff --git a/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json new file mode 100644 index 000000000..f740e20b4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-asg-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep new file mode 100644 index 000000000..924f02eb5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. Name of the Application Security Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource applicationSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${applicationSecurityGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: applicationSecurityGroup +} + +module applicationSecurityGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppSecurityGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: applicationSecurityGroup.id + } +}] + +@description('The resource group the application security group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the application security group') +output resourceId string = applicationSecurityGroup.id + +@description('The name of the application security group') +output name string = applicationSecurityGroup.name diff --git a/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/readme.md b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/readme.md new file mode 100644 index 000000000..1f3d51fe7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/readme.md @@ -0,0 +1,92 @@ +# Application Security Groups `[Microsoft.Network/applicationSecurityGroups]` + +This module deploys an application security group. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/applicationSecurityGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Application Security Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application security group | +| `resourceGroupName` | string | The resource group the application security group was deployed into | +| `resourceId` | string | The resource ID of the application security group | + +## Template references + +- [Applicationsecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/applicationSecurityGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/version.json b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/applicationSecurityGroups/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/carml/1.2.0/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c2ca9c2a9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/azureFirewalls/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(azureFirewall.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: azureFirewall +}] diff --git a/carml/1.2.0/Microsoft.Network/azureFirewalls/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/azureFirewalls/.parameters/parameters.json new file mode 100644 index 000000000..864f62df5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/azureFirewalls/.parameters/parameters.json @@ -0,0 +1,135 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-azfw-x-001" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + }, + "ipConfigurations": { + "value": [ + { + "name": "ipConfig01", + "publicIPAddressResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-fw", + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-azfw/subnets/AzureFirewallSubnet" + } + ] + }, + "applicationRuleCollections": { + "value": [ + { + "name": "allow-app-rules", + "properties": { + "priority": 100, + "action": { + "type": "allow" + }, + "rules": [ + { + "name": "allow-ase-tags", + "sourceAddresses": [ + "*" + ], + "protocols": [ + { + "protocolType": "HTTP", + "port": "80" + }, + { + "protocolType": "HTTPS", + "port": "443" + } + ], + "fqdnTags": [ + "AppServiceEnvironment", + "WindowsUpdate" + ] + }, + { + "name": "allow-ase-management", + "sourceAddresses": [ + "*" + ], + "protocols": [ + { + "protocolType": "HTTP", + "port": "80" + }, + { + "protocolType": "HTTPS", + "port": "443" + } + ], + "targetFqdns": [ + "management.azure.com" + ] + } + ] + } + } + ] + }, + "networkRuleCollections": { + "value": [ + { + "name": "allow-network-rules", + "properties": { + "priority": 100, + "action": { + "type": "allow" + }, + "rules": [ + { + "name": "allow-ntp", + "sourceAddresses": [ + "*" + ], + "destinationAddresses": [ + "*" + ], + "destinationPorts": [ + "123", + "12000" + ], + "protocols": [ + "Any" + ] + } + ] + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/azureFirewalls/deploy.bicep b/carml/1.2.0/Microsoft.Network/azureFirewalls/deploy.bicep new file mode 100644 index 000000000..b60a82504 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/azureFirewalls/deploy.bicep @@ -0,0 +1,224 @@ +@description('Required. Name of the Azure Firewall.') +param name string + +@description('Optional. Name of an Azure Firewall SKU.') +@allowed([ + 'AZFW_VNet' + 'AZFW_Hub' +]) +param azureSkuName string = 'AZFW_VNet' + +@description('Optional. Tier of an Azure Firewall.') +@allowed([ + 'Standard' + 'Premium' +]) +param azureSkuTier string = 'Standard' + +@description('Optional. Collection of application rule collections used by Azure Firewall.') +param applicationRuleCollections array = [] + +@description('Optional. Collection of network rule collections used by Azure Firewall.') +param networkRuleCollections array = [] + +@description('Optional. Collection of NAT rule collections used by Azure Firewall.') +param natRuleCollections array = [] + +@description('Required. List of IP Configurations.') +param ipConfigurations array + +@description('Optional. Resource ID of the Firewall Policy that should be attached.') +param firewallPolicyId string = '' + +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +@description('Optional. The operation mode for Threat Intel.') +param threatIntelMode string = 'Deny' + +@description('Optional. Zone numbers e.g. 1,2,3.') +param zones array = [ + '1' + '2' + '3' +] + +@description('Optional. Diagnostic Storage Account resource identifier') +param diagnosticStorageAccountId string = '' + +@description('Optional. Log Analytics workspace resource identifier') +param diagnosticWorkspaceId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the Azure Firewall resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of firewall logs that will be streamed.') +@allowed([ + 'AzureFirewallApplicationRule' + 'AzureFirewallNetworkRule' + 'AzureFirewallDnsProxy' +]) +param diagnosticLogCategoriesToEnable array = [ + 'AzureFirewallApplicationRule' + 'AzureFirewallNetworkRule' + 'AzureFirewallDnsProxy' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +var ipConfigurations_var = [for ipConfiguration in ipConfigurations: { + name: ipConfiguration.name + properties: { + publicIPAddress: contains(ipConfiguration, 'publicIPAddressResourceId') ? { + id: ipConfiguration.publicIPAddressResourceId + } : null + subnet: contains(ipConfiguration, 'subnetResourceId') ? { + id: ipConfiguration.subnetResourceId + } : null + } +}] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2021-05-01' = { + name: name + location: location + zones: length(zones) == 0 ? null : zones + tags: tags + properties: { + threatIntelMode: threatIntelMode + firewallPolicy: empty(firewallPolicyId) ? null : { + id: firewallPolicyId + } + ipConfigurations: ipConfigurations_var + sku: { + name: azureSkuName + tier: azureSkuTier + } + applicationRuleCollections: applicationRuleCollections + natRuleCollections: natRuleCollections + networkRuleCollections: networkRuleCollections + } +} + +resource azureFirewall_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureFirewall.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureFirewall +} + +resource azureFirewall_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: azureFirewall +} + +module azureFirewall_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AzFW-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureFirewall.id + } +}] + +@description('The resource ID of the Azure firewall') +output resourceId string = azureFirewall.id + +@description('The name of the Azure firewall') +output name string = azureFirewall.name + +@description('The resource group the Azure firewall was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The private IP of the Azure firewall') +output privateIp string = azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + +@description('List of Application Rule Collections') +output applicationRuleCollections array = applicationRuleCollections + +@description('List of Network Rule Collections') +output networkRuleCollections array = networkRuleCollections + +@description('Collection of NAT rule collections used by Azure Firewall') +output natRuleCollections array = natRuleCollections diff --git a/carml/1.2.0/Microsoft.Network/azureFirewalls/readme.md b/carml/1.2.0/Microsoft.Network/azureFirewalls/readme.md new file mode 100644 index 000000000..ab565b8cc --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/azureFirewalls/readme.md @@ -0,0 +1,121 @@ +# Azure Firewalls `[Microsoft.Network/azureFirewalls]` + +This module deploys a firewall. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/azureFirewalls` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `ipConfigurations` | array | List of IP Configurations. | +| `name` | string | Name of the Azure Firewall. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `applicationRuleCollections` | array | `[]` | | Collection of application rule collections used by Azure Firewall. | +| `azureSkuName` | string | `'AZFW_VNet'` | `[AZFW_VNet, AZFW_Hub]` | Name of an Azure Firewall SKU. | +| `azureSkuTier` | string | `'Standard'` | `[Standard, Premium]` | Tier of an Azure Firewall. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[AzureFirewallApplicationRule, AzureFirewallNetworkRule, AzureFirewallDnsProxy]` | `[AzureFirewallApplicationRule, AzureFirewallNetworkRule, AzureFirewallDnsProxy]` | The name of firewall logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Diagnostic Storage Account resource identifier | +| `diagnosticWorkspaceId` | string | `''` | | Log Analytics workspace resource identifier | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `firewallPolicyId` | string | `''` | | Resource ID of the Firewall Policy that should be attached. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `natRuleCollections` | array | `[]` | | Collection of NAT rule collections used by Azure Firewall. | +| `networkRuleCollections` | array | `[]` | | Collection of network rule collections used by Azure Firewall. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the Azure Firewall resource. | +| `threatIntelMode` | string | `'Deny'` | `[Alert, Deny, Off]` | The operation mode for Threat Intel. | +| `zones` | array | `[1, 2, 3]` | | Zone numbers e.g. 1,2,3. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `applicationRuleCollections` | array | List of Application Rule Collections | +| `name` | string | The name of the Azure firewall | +| `natRuleCollections` | array | Collection of NAT rule collections used by Azure Firewall | +| `networkRuleCollections` | array | List of Network Rule Collections | +| `privateIp` | string | The private IP of the Azure firewall | +| `resourceGroupName` | string | The resource group the Azure firewall was deployed into | +| `resourceId` | string | The resource ID of the Azure firewall | + +## Considerations + +The `applicationRuleCollections` parameter accepts a JSON Array of AzureFirewallApplicationRule objects. +The `networkRuleCollections` parameter accepts a JSON Array of AzureFirewallNetworkRuleCollection objects. + +## Template references + +- [Azurefirewalls](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/azureFirewalls) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/azureFirewalls/version.json b/carml/1.2.0/Microsoft.Network/azureFirewalls/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/azureFirewalls/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/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep b/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep new file mode 100644 index 000000000..cc9a0eb90 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress.bicep @@ -0,0 +1,153 @@ +@description('Required. The name of the Public IP Address') +param name string + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. The public IP address allocation method. - Static or Dynamic.') +param publicIPAllocationMethod string = 'Dynamic' + +@description('Optional. Public IP Address sku Name') +param skuName string = 'Basic' + +@description('Optional. Public IP Address pricing tier') +param skuTier string = 'Regional' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource identifier of log analytics.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIPPrefix = { + id: publicIPPrefixResourceId +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + properties: { + publicIPAddressVersion: 'IPv4' + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + idleTimeoutInMinutes: 4 + ipTags: [] + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac 'nested_publicIPAddress_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The resource group the public IP address was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address') +output resourceId string = publicIpAddress.id diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep b/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep new file mode 100644 index 000000000..87e8e8d34 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_publicIPAddress_rbac.bicep @@ -0,0 +1,61 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Microsoft OneAsset Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reservation Purchaser': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpAddress +}] diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..08f2129f0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/.bicep/nested_rbac.bicep @@ -0,0 +1,60 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'ExpressRoute Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource azureBastion 'Microsoft.Network/bastionHosts@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(azureBastion.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: azureBastion +}] diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/bastionHosts/.parameters/min.parameters.json new file mode 100644 index 000000000..6ef38853f --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/.parameters/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": "<>-az-bas-min-001" + }, + "vNetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-002" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/bastionHosts/.parameters/parameters.json new file mode 100644 index 000000000..0b1cd0d25 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/.parameters/parameters.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-bas-x-001" + }, + "vNetId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "publicIPAddressId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-bas" + }, + "skuType": { + "value": "Standard" + }, + "scaleUnits": { + "value": 4 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/deploy.bicep b/carml/1.2.0/Microsoft.Network/bastionHosts/deploy.bicep new file mode 100644 index 000000000..8a0d46168 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/deploy.bicep @@ -0,0 +1,197 @@ +@description('Required. Name of the Azure Bastion resource') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Shared services Virtual Network resource identifier') +param vNetId string + +@description('Optional. Specifies the resource ID of the existing public IP to be leveraged by Azure Bastion.') +param publicIPAddressId string = '' + +@description('Optional. Specifies the properties of the public IP to create and be used by Azure Bastion. If it\'s not provided and publicIPAddressId is empty, a \'-pip\' suffix will be appended to the Bastion\'s name.') +param publicIPAddressObject object = {} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@allowed([ + 'Basic' + 'Standard' +]) +@description('Optional. The SKU of this Bastion Host.') +param skuType string = 'Basic' + +@description('Optional. The scale units for the Bastion Host resource.') +param scaleUnits int = 2 + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Optional. The name of bastion logs that will be streamed.') +@allowed([ + 'BastionAuditLogs' +]) +param diagnosticLogCategoriesToEnable array = [ + 'BastionAuditLogs' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var scaleUnits_var = skuType == 'Basic' ? 2 : scaleUnits + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource publicIPAddressExisting 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = if (!empty(publicIPAddressId)) { + name: last(split(publicIPAddressId, '/')) + scope: resourceGroup(split(publicIPAddressId, '/')[2], split(publicIPAddressId, '/')[4]) +} + +module publicIPAddress '.bicep/nested_publicIPAddress.bicep' = if (empty(publicIPAddressId)) { + name: '${uniqueString(deployment().name, location)}-Bastion-PIP' + params: { + name: contains(publicIPAddressObject, 'name') ? (!(empty(publicIPAddressObject.name)) ? publicIPAddressObject.name : '${name}-pip') : '${name}-pip' + publicIPPrefixResourceId: contains(publicIPAddressObject, 'publicIPPrefixResourceId') ? (!(empty(publicIPAddressObject.publicIPPrefixResourceId)) ? publicIPAddressObject.publicIPPrefixResourceId : '') : '' + publicIPAllocationMethod: contains(publicIPAddressObject, 'publicIPAllocationMethod') ? (!(empty(publicIPAddressObject.publicIPAllocationMethod)) ? publicIPAddressObject.publicIPAllocationMethod : 'Static') : 'Static' + skuName: contains(publicIPAddressObject, 'skuName') ? (!(empty(publicIPAddressObject.skuName)) ? publicIPAddressObject.skuName : 'Standard') : 'Standard' + skuTier: contains(publicIPAddressObject, 'skuTier') ? (!(empty(publicIPAddressObject.skuTier)) ? publicIPAddressObject.skuTier : 'Regional') : 'Regional' + roleAssignments: contains(publicIPAddressObject, 'roleAssignments') ? (!empty(publicIPAddressObject.roleAssignments) ? publicIPAddressObject.roleAssignments : []) : [] + diagnosticMetricsToEnable: contains(publicIPAddressObject, 'diagnosticMetricsToEnable') ? (!(empty(publicIPAddressObject.diagnosticMetricsToEnable)) ? publicIPAddressObject.diagnosticMetricsToEnable : [ + 'AllMetrics' + ]) : [ + 'AllMetrics' + ] + diagnosticLogCategoriesToEnable: contains(publicIPAddressObject, 'diagnosticLogCategoriesToEnable') ? (!(empty(publicIPAddressObject.diagnosticLogCategoriesToEnable)) ? publicIPAddressObject.diagnosticLogCategoriesToEnable : [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' + ]) : [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' + ] + location: location + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticWorkspaceId: diagnosticWorkspaceId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + lock: lock + tags: tags + } +} + +resource azureBastion 'Microsoft.Network/bastionHosts@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuType + } + properties: { + scaleUnits: scaleUnits_var + ipConfigurations: [ + { + name: 'IpConf' + properties: { + subnet: { + id: '${vNetId}/subnets/AzureBastionSubnet' + } + publicIPAddress: { + id: !(empty(publicIPAddressId)) ? publicIPAddressId : publicIPAddress.outputs.resourceId + } + } + } + ] + } +} + +resource azureBastion_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${azureBastion.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: azureBastion +} + +resource azureBastion_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: azureBastion +} + +module azureBastion_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Bastion-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: azureBastion.id + } +}] + +@description('The resource group the Azure Bastion was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name the Azure Bastion') +output name string = azureBastion.name + +@description('The resource ID the Azure Bastion') +output resourceId string = azureBastion.id diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/readme.md b/carml/1.2.0/Microsoft.Network/bastionHosts/readme.md new file mode 100644 index 000000000..b0dd8761c --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/readme.md @@ -0,0 +1,108 @@ +# Bastion Hosts `[Microsoft.Network/bastionHosts]` + +This module deploys a bastion host. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/bastionHosts` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Bastion resource | +| `vNetId` | string | Shared services Virtual Network resource identifier | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[BastionAuditLogs]` | `[BastionAuditLogs]` | Optional. The name of bastion logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicIPAddressId` | string | `''` | | Specifies the resource ID of the existing public IP to be leveraged by Azure Bastion. | +| `publicIPAddressObject` | object | `{object}` | | Specifies the properties of the public IP to create and be used by Azure Bastion. If it's not provided and publicIPAddressId is empty, a '-pip' suffix will be appended to the Bastion's name. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `scaleUnits` | int | `2` | | The scale units for the Bastion Host resource. | +| `skuType` | string | `'Basic'` | `[Basic, Standard]` | The SKU of this Bastion Host. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name the Azure Bastion | +| `resourceGroupName` | string | The resource group the Azure Bastion was deployed into | +| `resourceId` | string | The resource ID the Azure Bastion | + +## Template references + +- [Bastionhosts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/bastionHosts) +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/bastionHosts/version.json b/carml/1.2.0/Microsoft.Network/bastionHosts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/bastionHosts/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/carml/1.2.0/Microsoft.Network/connections/.parameters/vnet2vnet.parameters.json b/carml/1.2.0/Microsoft.Network/connections/.parameters/vnet2vnet.parameters.json new file mode 100644 index 000000000..b1734ef61 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/connections/.parameters/vnet2vnet.parameters.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnetgwc-x-001" + }, + "virtualNetworkGateway1": { + "value": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworkGateways/<>-az-vnet-vpn-gw-p-001" + } + }, + "virtualNetworkGateway2": { + "value": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworkGateways/<>-az-vnet-vpn-gw-p-002" + } + }, + "vpnSharedKey": { + "reference": { + "keyVault": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + }, + "secretName": "vpnSharedKey" + } + }, + "virtualNetworkGatewayConnectionType": { + "value": "Vnet2Vnet" + }, + "enableBgp": { + "value": false + }, + "location": { + "value": "eastus" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/connections/deploy.bicep b/carml/1.2.0/Microsoft.Network/connections/deploy.bicep new file mode 100644 index 000000000..cdf3fdaaa --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/connections/deploy.bicep @@ -0,0 +1,125 @@ +@description('Required. Remote connection name') +param name string + +@description('Optional. Specifies a VPN shared key. The same value has to be specified on both Virtual Network Gateways') +param vpnSharedKey string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Gateway connection type.') +@allowed([ + 'IPsec' + 'Vnet2Vnet' + 'ExpressRoute' + 'VPNClient' +]) +param virtualNetworkGatewayConnectionType string = 'IPsec' + +@description('Optional. Value to specify if BGP is enabled or not') +param enableBgp bool = false + +@description('Optional. Enable policy-based traffic selectors') +param usePolicyBasedTrafficSelectors bool = false + +@description('Optional. The IPSec Policies to be considered by this connection') +param customIPSecPolicy object = { + saLifeTimeSeconds: 0 + saDataSizeKilobytes: 0 + ipsecEncryption: '' + ipsecIntegrity: '' + ikeEncryption: '' + ikeIntegrity: '' + dhGroup: '' + pfsGroup: '' +} + +@description('Optional. The weight added to routes learned from this BGP speaker.') +param routingWeight int = -1 + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. The primary Virtual Network Gateway.') +param virtualNetworkGateway1 object + +@description('Optional. The remote Virtual Network Gateway. Used for connection type [Vnet2Vnet]') +param virtualNetworkGateway2 object = {} + +@description('Optional. The remote peer. Used for connection type [ExpressRoute]') +param peer object = {} + +@description('Optional. The local network gateway. Used for connection type [IPsec]') +param localNetworkGateway2 object = {} + +var customIPSecPolicy_var = [ + { + saLifeTimeSeconds: customIPSecPolicy.saLifeTimeSeconds + saDataSizeKilobytes: customIPSecPolicy.saDataSizeKilobytes + ipsecEncryption: customIPSecPolicy.ipsecEncryption + ipsecIntegrity: customIPSecPolicy.ipsecIntegrity + ikeEncryption: customIPSecPolicy.ikeEncryption + ikeIntegrity: customIPSecPolicy.ikeIntegrity + dhGroup: customIPSecPolicy.dhGroup + pfsGroup: customIPSecPolicy.pfsGroup + } +] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource connection 'Microsoft.Network/connections@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + connectionType: virtualNetworkGatewayConnectionType + virtualNetworkGateway1: virtualNetworkGateway1 + virtualNetworkGateway2: virtualNetworkGatewayConnectionType == 'Vnet2Vnet' ? virtualNetworkGateway2 : null + localNetworkGateway2: virtualNetworkGatewayConnectionType == 'Ipsec' ? localNetworkGateway2 : null + peer: virtualNetworkGatewayConnectionType == 'ExpressRoute' ? peer : null + sharedKey: virtualNetworkGatewayConnectionType != 'ExpressRoute' ? vpnSharedKey : null + usePolicyBasedTrafficSelectors: usePolicyBasedTrafficSelectors + ipsecPolicies: !empty(customIPSecPolicy.ipsecEncryption) ? customIPSecPolicy_var : customIPSecPolicy.ipsecEncryption + routingWeight: routingWeight != -1 ? routingWeight : null + enableBgp: enableBgp + } +} + +resource connection_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${connection.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: connection +} + +@description('The resource group the remote connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the remote connection') +output name string = connection.name + +@description('The resource ID of the remote connection') +output resourceId string = connection.id diff --git a/carml/1.2.0/Microsoft.Network/connections/readme.md b/carml/1.2.0/Microsoft.Network/connections/readme.md new file mode 100644 index 000000000..d4ca73abc --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/connections/readme.md @@ -0,0 +1,149 @@ +# Virtual Network Gateway Connections `[Microsoft.Network/connections]` + +This template deploys a virtual network gateway connection. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/connections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Remote connection name | +| `virtualNetworkGateway1` | object | The primary Virtual Network Gateway. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `customIPSecPolicy` | object | `{object}` | | The IPSec Policies to be considered by this connection | +| `enableBgp` | bool | `False` | | Value to specify if BGP is enabled or not | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `localNetworkGateway2` | object | `{object}` | | The local network gateway. Used for connection type [IPsec] | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `peer` | object | `{object}` | | The remote peer. Used for connection type [ExpressRoute] | +| `routingWeight` | int | `-1` | | The weight added to routes learned from this BGP speaker. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `usePolicyBasedTrafficSelectors` | bool | `False` | | Enable policy-based traffic selectors | +| `virtualNetworkGateway2` | object | `{object}` | | The remote Virtual Network Gateway. Used for connection type [Vnet2Vnet] | +| `virtualNetworkGatewayConnectionType` | string | `'IPsec'` | `[IPsec, Vnet2Vnet, ExpressRoute, VPNClient]` | Gateway connection type. | +| `vpnSharedKey` | string | `''` | | Specifies a VPN shared key. The same value has to be specified on both Virtual Network Gateways | + + +### Parameter Usage: `virtualNetworkGateway1` + +The primary virtual network gateway object. + +```json +"virtualNetworkGateway1" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/virtualNetworkGateways/myGateway01", +} +``` + +### Parameter Usage: `virtualNetworkGateway2` + +The secondary virtual network gateway used for VNET to VNET connections. + +```json +"virtualNetworkGateway2" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/virtualNetworkGateways/myGateway02"ss +} +``` + +### Parameter Usage: `localNetworkGateway2` + +The local virtual network gateway object. + +```json +"localNetworkGateway2" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/localNetworkGateways/myGateway" +} +``` + +### Parameter Usage: `peer` + +The remote peer object used for ExpressRoute connections + +```json +"peer" : { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myRG/providers/Microsoft.Network/expressRouteCircuits/expressRoute" +} +``` + +### Parameter Usage: `customIPSecPolicy` + +If ipsecEncryption parameter is empty, customIPSecPolicy will not be deployed. The parameter file should look like below. + +```json +"customIPSecPolicy": { + "value": { + "saLifeTimeSeconds": 0, + "saDataSizeKilobytes": 0, + "ipsecEncryption": "", + "ipsecIntegrity": "", + "ikeEncryption": "", + "ikeIntegrity": "", + "dhGroup": "", + "pfsGroup": "" + } +}, +``` + +Format of the full customIPSecPolicy parameter in parameter file. + +```json +"customIPSecPolicy": { + "value": { + "saLifeTimeSeconds": 28800, + "saDataSizeKilobytes": 102400000, + "ipsecEncryption": "AES256", + "ipsecIntegrity": "SHA256", + "ikeEncryption": "AES256", + "ikeIntegrity": "SHA256", + "dhGroup": "DHGroup14", + "pfsGroup": "None" + } +}, +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the remote connection | +| `resourceGroupName` | string | The resource group the remote connection was deployed into | +| `resourceId` | string | The resource ID of the remote connection | + +## Template references + +- [Connections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/connections) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.2.0/Microsoft.Network/connections/version.json b/carml/1.2.0/Microsoft.Network/connections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/connections/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/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e350577b6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(ddosProtectionPlan.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: ddosProtectionPlan +}] diff --git a/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json new file mode 100644 index 000000000..3d697dee9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/.parameters/parameters.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ddos-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/deploy.bicep b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/deploy.bicep new file mode 100644 index 000000000..ecd0083f4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/deploy.bicep @@ -0,0 +1,71 @@ +@description('Required. Name of the DDoS protection plan to assign the VNET to.') +@minLength(1) +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource ddosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource ddosProtectionPlan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${ddosProtectionPlan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: ddosProtectionPlan +} + +module ddosProtectionPlan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-DDoSProtectionPlan-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: ddosProtectionPlan.id + } +}] + +@description('The resource group the DDOS protection plan was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the DDOS protection plan') +output resourceId string = ddosProtectionPlan.id + +@description('The name of the DDOS protection plan') +output name string = ddosProtectionPlan.name diff --git a/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/readme.md b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/readme.md new file mode 100644 index 000000000..0f2bd2762 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/readme.md @@ -0,0 +1,92 @@ +# DDoS Protection Plans `[Microsoft.Network/ddosProtectionPlans]` + +This template deploys a DDoS protection plan. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/ddosProtectionPlans` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | `''` | Name of the DDoS protection plan to assign the VNET to. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the DDOS protection plan | +| `resourceGroupName` | string | The resource group the DDOS protection plan was deployed into | +| `resourceId` | string | The resource ID of the DDOS protection plan | + +## Template references + +- [Ddosprotectionplans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/ddosProtectionPlans) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/version.json b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ddosProtectionPlans/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/carml/1.2.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..9136bdf8c --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(expressRouteCircuits.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: expressRouteCircuits +}] diff --git a/carml/1.2.0/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json new file mode 100644 index 000000000..8050f4406 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-erc-x-001" + }, + "serviceProviderName": { + "value": "Equinix" + }, + "peeringLocation": { + "value": "Amsterdam" + }, + "bandwidthInMbps": { + "value": 50 + }, + "skuTier": { + "value": "Standard" + }, + "skuFamily": { + "value": "MeteredData" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/expressRouteCircuits/deploy.bicep b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/deploy.bicep new file mode 100644 index 000000000..fb217b5d0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/deploy.bicep @@ -0,0 +1,220 @@ +@description('Required. This is the name of the ExpressRoute circuit') +param name string + +@description('Required. This is the name of the ExpressRoute Service Provider. It must exactly match one of the Service Providers from List ExpressRoute Service Providers API call.') +param serviceProviderName string + +@description('Required. This is the name of the peering location and not the ARM resource location. It must exactly match one of the available peering locations from List ExpressRoute Service Providers API call.') +param peeringLocation string + +@description('Required. This is the bandwidth in Mbps of the circuit being created. It must exactly match one of the available bandwidth offers List ExpressRoute Service Providers API call.') +param bandwidthInMbps int + +@description('Required. Chosen SKU Tier of ExpressRoute circuit. Choose from Local, Premium or Standard SKU tiers.') +@allowed([ + 'Local' + 'Standard' + 'Premium' +]) +param skuTier string = 'Standard' + +@description('Required. Chosen SKU family of ExpressRoute circuit. Choose from MeteredData or UnlimitedData SKU families.') +@allowed([ + 'MeteredData' + 'UnlimitedData' +]) +param skuFamily string = 'MeteredData' + +@description('Optional. Enabled BGP peering type for the Circuit.') +@allowed([ + true + false +]) +param peering bool = false + +@description('Optional. BGP peering type for the Circuit. Choose from AzurePrivatePeering, AzurePublicPeering or MicrosoftPeering.') +@allowed([ + 'AzurePrivatePeering' + 'MicrosoftPeering' +]) +param peeringType string = 'AzurePrivatePeering' + +@description('Optional. The shared key for peering configuration. Router does MD5 hash comparison to validate the packets sent by BGP connection. This parameter is optional and can be removed from peering configuration if not required.') +param sharedKey string = '' + +@description('Optional. The autonomous system number of the customer/connectivity provider.') +param peerASN int = 0 + +@description('Optional. A /30 subnet used to configure IP addresses for interfaces on Link1.') +param primaryPeerAddressPrefix string = '' + +@description('Optional. A /30 subnet used to configure IP addresses for interfaces on Link2.') +param secondaryPeerAddressPrefix string = '' + +@description('Optional. Specifies the identifier that is used to identify the customer.') +param vlanId int = 0 + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'PeeringRouteLog' +]) +param diagnosticLogCategoriesToEnable array = [ + 'PeeringRouteLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var peeringConfiguration = [ + { + name: peeringType + properties: { + peeringType: peeringType + sharedKey: sharedKey + peerASN: peerASN + primaryPeerAddressPrefix: primaryPeerAddressPrefix + secondaryPeerAddressPrefix: secondaryPeerAddressPrefix + vlanId: vlanId + } + } +] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource expressRouteCircuits 'Microsoft.Network/expressRouteCircuits@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: '${skuTier}_${skuFamily}' + tier: skuTier + family: skuTier == 'Local' ? 'UnlimitedData' : skuFamily + } + properties: { + serviceProviderProperties: { + serviceProviderName: serviceProviderName + peeringLocation: peeringLocation + bandwidthInMbps: bandwidthInMbps + } + peerings: peering ? peeringConfiguration : null + } +} + +resource expressRouteCircuits_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${expressRouteCircuits.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: expressRouteCircuits +} + +resource expressRouteCircuits_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: expressRouteCircuits +} + +module expressRouteCircuits_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ExpRouteCircuits-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: expressRouteCircuits.id + } +}] + +@description('The resource ID of express route curcuit') +output resourceId string = expressRouteCircuits.id + +@description('The resource group the express route curcuit was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of express route curcuit') +output name string = expressRouteCircuits.name + +@description('The service key of the express route circuit') +output serviceKey string = reference(expressRouteCircuits.id, '2021-02-01').serviceKey diff --git a/carml/1.2.0/Microsoft.Network/expressRouteCircuits/readme.md b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/readme.md new file mode 100644 index 000000000..72bcf034d --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/readme.md @@ -0,0 +1,115 @@ +# ExpressRoute Circuits `[Microsoft.Network/expressRouteCircuits]` + +This template deploys an express route circuit. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/expressRouteCircuits` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `bandwidthInMbps` | int | | | This is the bandwidth in Mbps of the circuit being created. It must exactly match one of the available bandwidth offers List ExpressRoute Service Providers API call. | +| `name` | string | | | This is the name of the ExpressRoute circuit | +| `peeringLocation` | string | | | This is the name of the peering location and not the ARM resource location. It must exactly match one of the available peering locations from List ExpressRoute Service Providers API call. | +| `serviceProviderName` | string | | | This is the name of the ExpressRoute Service Provider. It must exactly match one of the Service Providers from List ExpressRoute Service Providers API call. | +| `skuFamily` | string | `'MeteredData'` | `[MeteredData, UnlimitedData]` | Chosen SKU family of ExpressRoute circuit. Choose from MeteredData or UnlimitedData SKU families. | +| `skuTier` | string | `'Standard'` | `[Local, Standard, Premium]` | Chosen SKU Tier of ExpressRoute circuit. Choose from Local, Premium or Standard SKU tiers. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[PeeringRouteLog]` | `[PeeringRouteLog]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `peerASN` | int | `0` | | The autonomous system number of the customer/connectivity provider. | +| `peering` | bool | `False` | `[True, False]` | Enabled BGP peering type for the Circuit. | +| `peeringType` | string | `'AzurePrivatePeering'` | `[AzurePrivatePeering, MicrosoftPeering]` | BGP peering type for the Circuit. Choose from AzurePrivatePeering, AzurePublicPeering or MicrosoftPeering. | +| `primaryPeerAddressPrefix` | string | `''` | | A /30 subnet used to configure IP addresses for interfaces on Link1. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `secondaryPeerAddressPrefix` | string | `''` | | A /30 subnet used to configure IP addresses for interfaces on Link2. | +| `sharedKey` | string | `''` | | The shared key for peering configuration. Router does MD5 hash comparison to validate the packets sent by BGP connection. This parameter is optional and can be removed from peering configuration if not required. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `vlanId` | int | `0` | | Specifies the identifier that is used to identify the customer. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of express route curcuit | +| `resourceGroupName` | string | The resource group the express route curcuit was deployed into | +| `resourceId` | string | The resource ID of express route curcuit | +| `serviceKey` | string | The service key of the express route circuit | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Expressroutecircuits](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/expressRouteCircuits) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/expressRouteCircuits/version.json b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/expressRouteCircuits/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/carml/1.2.0/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json new file mode 100644 index 000000000..bb555089e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fwpol-min-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/firewallPolicies/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/firewallPolicies/.parameters/parameters.json new file mode 100644 index 000000000..67e03ad34 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/.parameters/parameters.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fwpol-x-002" + }, + "ruleCollectionGroups": { + "value": [ + { + "name": "<>-rule-001", + "priority": 5000, + "ruleCollections": [ + { + "name": "collection002", + "priority": 5555, + "action": { + "type": "Allow" + }, + "rules": [ + { + "name": "rule002", + "ipProtocols": [ + "TCP", + "UDP" + ], + "destinationPorts": [ + "80" + ], + "sourceAddresses": [ + "*" + ], + "sourceIpGroups": [], + "ruleType": "NetworkRule", + "destinationIpGroups": [], + "destinationAddresses": [ + "*" + ], + "destinationFqdns": [] + } + ], + "ruleCollectionType": "FirewallPolicyFilterRuleCollection" + } + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/firewallPolicies/deploy.bicep b/carml/1.2.0/Microsoft.Network/firewallPolicies/deploy.bicep new file mode 100644 index 000000000..3188cb5cb --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/deploy.bicep @@ -0,0 +1,179 @@ +@description('Required. Name of the Firewall Policy.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Firewall policy resource.') +param tags object = {} + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Resource ID of the base policy.') +param basePolicyResourceId string = '' + +@description('Optional. Enable DNS Proxy on Firewalls attached to the Firewall Policy.') +param enableProxy bool = false + +@description('Optional. List of Custom DNS Servers.') +param servers array = [] + +@description('Optional. A flag to indicate if the insights are enabled on the policy.') +param insightsIsEnabled bool = false + +@description('Optional. Default Log Analytics Resource ID for Firewall Policy Insights.') +param defaultWorkspaceId string = '' + +@description('Optional. List of workspaces for Firewall Policy Insights.') +param workspaces array = [] + +@description('Optional. Number of days the insights should be enabled on the policy.') +param retentionDays int = 365 + +@description('Optional. List of rules for traffic to bypass.') +param bypassTrafficSettings array = [] + +@description('Optional. List of specific signatures states.') +param signatureOverrides array = [] + +@description('Optional. The configuring of intrusion detection.') +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +param mode string = 'Off' + +@description('Optional. Tier of Firewall Policy.') +@allowed([ + 'Premium' + 'Standard' +]) +param tier string = 'Standard' + +@description('Optional. List of private IP addresses/IP address ranges to not be SNAT.') +param privateRanges array = [] + +@description('Optional. The operation mode for Threat Intel.') +@allowed([ + 'Alert' + 'Deny' + 'Off' +]) +param threatIntelMode string = 'Off' + +@description('Optional. List of FQDNs for the ThreatIntel Allowlist.') +param fqdns array = [] + +@description('Optional. List of IP addresses for the ThreatIntel Allowlist.') +param ipAddresses array = [] + +@description('Optional. Secret ID of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault. ') +param keyVaultSecretId string = '' + +@description('Optional. Name of the CA certificate.') +param certificateName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Rule collection groups.') +param ruleCollectionGroups array = [] + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + basePolicy: !empty(basePolicyResourceId) ? { + id: basePolicyResourceId + } : null + dnsSettings: enableProxy ? { + enableProxy: enableProxy + servers: servers + } : null + insights: insightsIsEnabled ? { + isEnabled: insightsIsEnabled + logAnalyticsResources: { + defaultWorkspaceId: { + id: !empty(defaultWorkspaceId) ? defaultWorkspaceId : null + } + workspaces: !empty(workspaces) ? workspaces : null + } + retentionDays: retentionDays + } : null + intrusionDetection: (mode != 'Off') ? { + configuration: { + bypassTrafficSettings: !empty(bypassTrafficSettings) ? bypassTrafficSettings : null + signatureOverrides: !empty(signatureOverrides) ? signatureOverrides : null + } + mode: mode + } : null + sku: { + tier: tier + } + snat: !empty(privateRanges) ? { + privateRanges: privateRanges + } : null + threatIntelMode: threatIntelMode + threatIntelWhitelist: { + fqdns: fqdns + ipAddresses: ipAddresses + } + transportSecurity: (!empty(keyVaultSecretId) || !empty(certificateName)) ? { + certificateAuthority: { + keyVaultSecretId: !empty(keyVaultSecretId) ? keyVaultSecretId : null + name: !empty(certificateName) ? certificateName : null + } + } : null + } +} + +// When a FW policy uses a base policy and have more rule collection groups, +// they need to be deployed sequentially, otherwise the deployment would fail +// because of concurrent access to the base policy. +// The next line forces ARM to deploy them one after the other, so no race concition on the base policy will happen. +@batchSize(1) +module firewallPolicy_ruleCollectionGroups 'ruleCollectionGroups/deploy.bicep' = [for (ruleCollectionGroup, index) in ruleCollectionGroups: { + name: '${uniqueString(deployment().name, location)}-firewallPolicy_ruleCollectionGroups-${index}' + params: { + firewallPolicyName: firewallPolicy.name + name: ruleCollectionGroup.name + priority: ruleCollectionGroup.priority + ruleCollections: ruleCollectionGroup.ruleCollections + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the deployed firewall policy') +output name string = firewallPolicy.name + +@description('The resource ID of the deployed firewall policy') +output resourceId string = firewallPolicy.id + +@description('The resource group of the deployed firewall policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/firewallPolicies/readme.md b/carml/1.2.0/Microsoft.Network/firewallPolicies/readme.md new file mode 100644 index 000000000..108bb0dec --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/readme.md @@ -0,0 +1,95 @@ +# Firewall Policies `[Microsoft.Network/firewallPolicies]` + +This module deploys Firewall Policies. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies` | 2021-05-01 | +| `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Firewall Policy. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `basePolicyResourceId` | string | `''` | | Resource ID of the base policy. | +| `bypassTrafficSettings` | array | `[]` | | List of rules for traffic to bypass. | +| `certificateName` | string | `''` | | Name of the CA certificate. | +| `defaultWorkspaceId` | string | `''` | | Default Log Analytics Resource ID for Firewall Policy Insights. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableProxy` | bool | `False` | | Enable DNS Proxy on Firewalls attached to the Firewall Policy. | +| `fqdns` | array | `[]` | | List of FQDNs for the ThreatIntel Allowlist. | +| `insightsIsEnabled` | bool | `False` | | A flag to indicate if the insights are enabled on the policy. | +| `ipAddresses` | array | `[]` | | List of IP addresses for the ThreatIntel Allowlist. | +| `keyVaultSecretId` | string | `''` | | Secret ID of (base-64 encoded unencrypted pfx) Secret or Certificate object stored in KeyVault. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `mode` | string | `'Off'` | `[Alert, Deny, Off]` | The configuring of intrusion detection. | +| `privateRanges` | array | `[]` | | List of private IP addresses/IP address ranges to not be SNAT. | +| `retentionDays` | int | `365` | | Number of days the insights should be enabled on the policy. | +| `ruleCollectionGroups` | _[ruleCollectionGroups](ruleCollectionGroups/readme.md)_ array | `[]` | | Rule collection groups. | +| `servers` | array | `[]` | | List of Custom DNS Servers. | +| `signatureOverrides` | array | `[]` | | List of specific signatures states. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the Firewall policy resource. | +| `threatIntelMode` | string | `'Off'` | `[Alert, Deny, Off]` | The operation mode for Threat Intel. | +| `tier` | string | `'Standard'` | `[Premium, Standard]` | Tier of Firewall Policy. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `workspaces` | array | `[]` | | List of workspaces for Firewall Policy Insights. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed firewall policy | +| `resourceGroupName` | string | The resource group of the deployed firewall policy | +| `resourceId` | string | The resource ID of the deployed firewall policy | + +## Template references + +- [Firewallpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies) +- [Firewallpolicies/Rulecollectiongroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies/ruleCollectionGroups) diff --git a/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep b/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep new file mode 100644 index 000000000..bdf4650cc --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. Name of the Firewall Policy.') +param firewallPolicyName string + +@description('Required. The name of the rule collection group to deploy') +param name string + +@description('Required. Priority of the Firewall Policy Rule Collection Group resource.') +param priority int + +@description('Optional. Group of Firewall Policy rule collections.') +param ruleCollections array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource firewallPolicy 'Microsoft.Network/firewallPolicies@2021-05-01' existing = { + name: firewallPolicyName +} + +resource ruleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2021-05-01' = { + name: name + parent: firewallPolicy + properties: { + priority: priority + ruleCollections: ruleCollections + } +} + +@description('The name of the deployed rule collection group') +output name string = ruleCollectionGroup.name + +@description('The resource ID of the deployed rule collection group') +output resourceId string = ruleCollectionGroup.id + +@description('The resource group of the deployed rule collection group') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md b/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md new file mode 100644 index 000000000..702b54bd7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/readme.md @@ -0,0 +1,59 @@ +# Network Firewall Policies Rule Collection Groups `[Microsoft.Network/firewallPolicies/ruleCollectionGroups]` + +This module deploys Network Firewall Policies Rule Collection Groups. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/firewallPolicies/ruleCollectionGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `firewallPolicyName` | string | Name of the Firewall Policy. | +| `name` | string | The name of the rule collection group to deploy | +| `priority` | int | Priority of the Firewall Policy Rule Collection Group resource. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ruleCollections` | array | `[]` | Group of Firewall Policy rule collections. | + + +### Parameter Usage: `ruleCollections` + +For remaining properties, see [FirewallPolicyRuleCollection objects](https://docs.microsoft.com/en-us/azure/templates/microsoft.network/firewallpolicies/rulecollectiongroups?tabs=json#firewallpolicyrulecollection-objects) + +```json +"ruleCollections": [ + { + "name": "string", + "priority": "int", + "ruleCollectionType": "string" + // For remaining properties, see FirewallPolicyRuleCollection objects + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed rule collection group | +| `resourceGroupName` | string | The resource group of the deployed rule collection group | +| `resourceId` | string | The resource ID of the deployed rule collection group | + +## Template references + +- [Firewallpolicies/Rulecollectiongroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/firewallPolicies/ruleCollectionGroups) diff --git a/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/version.json b/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/ruleCollectionGroups/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/carml/1.2.0/Microsoft.Network/firewallPolicies/version.json b/carml/1.2.0/Microsoft.Network/firewallPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/firewallPolicies/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/carml/1.2.0/Microsoft.Network/frontDoors/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/frontDoors/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c96e0a3bb --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/frontDoors/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource frontDoor 'Microsoft.Network/frontDoors@2020-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(frontDoor.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: frontDoor +}] diff --git a/carml/1.2.0/Microsoft.Network/frontDoors/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/frontDoors/.parameters/parameters.json new file mode 100644 index 000000000..60be79daa --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/frontDoors/.parameters/parameters.json @@ -0,0 +1,112 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-fd-x-001" + }, + "backendPools": { + "value": [ + { + "name": "backendPool", + "properties": { + "backends": [ + { + "address": "biceptest.local", + "backendHostHeader": "backendAddress", + "httpPort": 80, + "httpsPort": 443, + "weight": 50, + "priority": 1, + "enabledState": "Enabled", + "privateLinkAlias": "", + "privateLinkApprovalMessage": "", + "privateLinkLocation": "", + "privateLinkResourceId": "" + } + ], + "LoadBalancingSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/LoadBalancingSettings/loadBalancer" + }, + "HealthProbeSettings": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/HealthProbeSettings/heathProbe" + } + } + } + ] + }, + "enforceCertificateNameCheck": { + "value": "Disabled" + }, + "sendRecvTimeoutSeconds": { + "value": 10 + }, + "frontendEndpoints": { + "value": [ + { + "name": "frontEnd", + "properties": { + "hostName": "<>-az-fd-x-001.azurefd.net", + "sessionAffinityEnabledState": "Disabled", + "sessionAffinityTtlSeconds": 60 + } + } + ] + }, + "healthProbeSettings": { + "value": [ + { + "name": "heathProbe", + "properties": { + "enabledState": "", + "healthProbeMethod": "", + "intervalInSeconds": 60, + "path": "/", + "protocol": "Https" + } + } + ] + }, + "loadBalancingSettings": { + "value": [ + { + "name": "loadBalancer", + "properties": { + "additionalLatencyMilliseconds": 0, + "sampleSize": 50, + "successfulSamplesRequired": 1 + } + } + ] + }, + "routingRules": { + "value": [ + { + "name": "routingRule", + "properties": { + "acceptedProtocols": [ + "Http", + "Https" + ], + "enabledState": "Enabled", + "frontendEndpoints": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/FrontendEndpoints/frontEnd" + } + ], + "patternsToMatch": [ + "/*" + ], + "routeConfiguration": { + "@odata.type": "#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration", + "forwardingProtocol": "MatchRequest", + "backendPool": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/frontDoors/<>-az-fd-x-001/BackendPools/backendPool" + } + } + } + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/frontDoors/deploy.bicep b/carml/1.2.0/Microsoft.Network/frontDoors/deploy.bicep new file mode 100644 index 000000000..ed615578a --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/frontDoors/deploy.bicep @@ -0,0 +1,178 @@ +@description('Required. The name of the frontDoor.') +@minLength(1) +@maxLength(64) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Required. Backend address pool of the frontdoor resource.') +param backendPools array = [] + +@description('Optional. Enforce certificate name check of the frontdoor resource.') +param enforceCertificateNameCheck string = 'Disabled' + +@description('Optional. Certificate name check time of the frontdoor resource.') +param sendRecvTimeoutSeconds int = 600 + +@description('Required. State of the frontdoor resource.') +param enabledState string = 'Enabled' + +@description('Required. Friendly name of the frontdoor resource.') +param friendlyName string = '' + +@description('Required. Frontend endpoints of the frontdoor resource.') +param frontendEndpoints array = [] + +@description('Required. Heath probe settings of the frontdoor resource.') +param healthProbeSettings array = [] + +@description('Required. Load balancing settings of the frontdoor resource.') +param loadBalancingSettings array = [] + +@description('Required. Routing rules settings of the frontdoor resource.') +param routingRules array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. ') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'FrontdoorAccessLog' + 'FrontdoorWebApplicationFirewallLog' +]) +param logsToEnable array = [ + 'FrontdoorAccessLog' + 'FrontdoorWebApplicationFirewallLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource frontDoor 'Microsoft.Network/frontDoors@2020-05-01' = { + name: name + location: 'global' + tags: tags + properties: { + backendPools: backendPools + backendPoolsSettings: { + enforceCertificateNameCheck: enforceCertificateNameCheck + sendRecvTimeoutSeconds: sendRecvTimeoutSeconds + } + enabledState: enabledState + friendlyName: friendlyName + frontendEndpoints: frontendEndpoints + healthProbeSettings: healthProbeSettings + loadBalancingSettings: loadBalancingSettings + routingRules: routingRules + } +} + +resource frontDoor_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${frontDoor.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: frontDoor +} + +resource frontDoor_diagnosticSettingName 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: '${frontDoor.name}-diagnosticSettings' + properties: { + storageAccountId: empty(diagnosticStorageAccountId) ? null : diagnosticStorageAccountId + workspaceId: empty(diagnosticWorkspaceId) ? null : diagnosticWorkspaceId + eventHubAuthorizationRuleId: empty(diagnosticEventHubAuthorizationRuleId) ? null : diagnosticEventHubAuthorizationRuleId + eventHubName: empty(diagnosticEventHubName) ? null : diagnosticEventHubName + metrics: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsMetrics + logs: empty(diagnosticStorageAccountId) && empty(diagnosticWorkspaceId) && empty(diagnosticEventHubAuthorizationRuleId) && empty(diagnosticEventHubName) ? null : diagnosticsLogs + } + scope: frontDoor +} + +module frontDoor_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-AppGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: frontDoor.id + } +}] + +@description('The name of the front door') +output name string = frontDoor.name + +@description('The resource ID of the front door') +output resourceId string = frontDoor.id + +@description('The resource group the front door was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/frontDoors/readme.md b/carml/1.2.0/Microsoft.Network/frontDoors/readme.md new file mode 100644 index 000000000..ef8e5057f --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/frontDoors/readme.md @@ -0,0 +1,111 @@ +# Front Doors `[Microsoft.Network/frontDoors]` + +This module deploys Front Doors. + + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/frontDoors` | 2020-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `backendPools` | array | `[]` | Backend address pool of the frontdoor resource. | +| `enabledState` | string | `'Enabled'` | State of the frontdoor resource. | +| `friendlyName` | string | `''` | Friendly name of the frontdoor resource. | +| `frontendEndpoints` | array | `[]` | Frontend endpoints of the frontdoor resource. | +| `healthProbeSettings` | array | `[]` | Heath probe settings of the frontdoor resource. | +| `loadBalancingSettings` | array | `[]` | Load balancing settings of the frontdoor resource. | +| `name` | string | | The name of the frontDoor. | +| `routingRules` | array | `[]` | Routing rules settings of the frontdoor resource. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enforceCertificateNameCheck` | string | `'Disabled'` | | Enforce certificate name check of the frontdoor resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `logsToEnable` | array | `[FrontdoorAccessLog, FrontdoorWebApplicationFirewallLog]` | `[FrontdoorAccessLog, FrontdoorWebApplicationFirewallLog]` | The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `sendRecvTimeoutSeconds` | int | `600` | | Certificate name check time of the frontdoor resource. | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the front door | +| `resourceGroupName` | string | The resource group the front door was deployed into | +| `resourceId` | string | The resource ID of the front door | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Frontdoors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-05-01/frontDoors) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/frontDoors/version.json b/carml/1.2.0/Microsoft.Network/frontDoors/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/frontDoors/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d6255df11 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ipGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource ipGroup 'Microsoft.Network/ipGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(ipGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: ipGroup +}] diff --git a/carml/1.2.0/Microsoft.Network/ipGroups/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/ipGroups/.parameters/parameters.json new file mode 100644 index 000000000..88c2f5a13 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ipGroups/.parameters/parameters.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "iacsGroup-servers" + }, + "ipAddresses": { + "value": [ + "10.0.0.1", + "10.0.0.2" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/ipGroups/deploy.bicep b/carml/1.2.0/Microsoft.Network/ipGroups/deploy.bicep new file mode 100644 index 000000000..ee21e30c1 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ipGroups/deploy.bicep @@ -0,0 +1,76 @@ +@description('Required. The name of the ipGroups.') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. IpAddresses/IpAddressPrefixes in the IpGroups resource.') +param ipAddresses array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource ipGroup 'Microsoft.Network/ipGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipAddresses: ipAddresses + } +} + +resource ipGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${ipGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: ipGroup +} + +module ipGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-IPGroup-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: ipGroup.id + } +}] + +@description('The resource ID of the IP group') +output resourceId string = ipGroup.id + +@description('The resource group of the IP group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the IP group') +output name string = ipGroup.name diff --git a/carml/1.2.0/Microsoft.Network/ipGroups/readme.md b/carml/1.2.0/Microsoft.Network/ipGroups/readme.md new file mode 100644 index 000000000..e1d5a45cb --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ipGroups/readme.md @@ -0,0 +1,93 @@ +# IP Groups `[Microsoft.Network/ipGroups]` + +This module deploys an IP group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/ipGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the ipGroups. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipAddresses` | array | `[]` | | IpAddresses/IpAddressPrefixes in the IpGroups resource. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Resource tags. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the IP group | +| `resourceGroupName` | string | The resource group of the IP group was deployed into | +| `resourceId` | string | The resource ID of the IP group | + +## Template references + +- [Ipgroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/ipGroups) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/ipGroups/version.json b/carml/1.2.0/Microsoft.Network/ipGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/ipGroups/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/carml/1.2.0/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..470e13b66 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(loadBalancer.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: loadBalancer +}] diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/internal.parameters.json b/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/internal.parameters.json new file mode 100644 index 000000000..4c3ffb022 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/internal.parameters.json @@ -0,0 +1,101 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-internal-001" + }, + "loadBalancerSku": { + "value": "Standard" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "privateIPConfig1", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + } + ] + }, + "backendAddressPools": { + "value": [ + { + "name": "servers" + } + ] + }, + "probes": { + "value": [ + { + "name": "probe1", + "protocol": "Tcp", + "port": "62000", + "intervalInSeconds": 5, + "numberOfProbes": 2 + } + ] + }, + "loadBalancingRules": { + "value": [ + { + "name": "privateIPLBRule1", + "frontendIPConfigurationName": "privateIPConfig1", + "frontendPort": 0, + "backendPort": 0, + "enableFloatingIP": true, + "idleTimeoutInMinutes": 4, + "protocol": "All", + "loadDistribution": "Default", + "probeName": "probe1", + "disableOutboundSnat": true, + "enableTcpReset": false, + "backendAddressPoolName": "servers" + } + ] + }, + "inboundNatRules": { + "value": [ + { + "name": "inboundNatRule1", + "frontendIPConfigurationName": "privateIPConfig1", + "frontendPort": 443, + "backendPort": 443, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 4, + "protocol": "Tcp", + "enableTcpReset": false + }, + { + "name": "inboundNatRule2", + "frontendIPConfigurationName": "privateIPConfig1", + "frontendPort": 3389, + "backendPort": 3389 + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/min.parameters.json new file mode 100644 index 000000000..695027dc9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/min.parameters.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-min-001" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "publicIPConfig1", + "publicIPAddressId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-min-lb" + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/parameters.json new file mode 100644 index 000000000..8ed786238 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/.parameters/parameters.json @@ -0,0 +1,126 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lb-x-001" + }, + "frontendIPConfigurations": { + "value": [ + { + "name": "publicIPConfig1", + "publicIPAddressId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/publicIPAddresses/adp-<>-az-pip-x-lb" + } + ] + }, + "backendAddressPools": { + "value": [ + { + "name": "backendAddressPool1" + }, + { + "name": "backendAddressPool2" + } + ] + }, + "loadBalancingRules": { + "value": [ + { + "name": "publicIPLBRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 80, + "backendPort": 80, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "protocol": "Tcp", + "enableTcpReset": false, + "loadDistribution": "Default", + "disableOutboundSnat": true, + "probeName": "probe1", + "backendAddressPoolName": "backendAddressPool1" + }, + { + "name": "publicIPLBRule2", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 8080, + "backendPort": 8080, + "loadDistribution": "Default", + "probeName": "probe2", + "backendAddressPoolName": "backendAddressPool2" + } + ] + }, + "inboundNatRules": { + "value": [ + { + "name": "inboundNatRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 443, + "backendPort": 443, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 4, + "protocol": "Tcp", + "enableTcpReset": false + }, + { + "name": "inboundNatRule2", + "frontendIPConfigurationName": "publicIPConfig1", + "frontendPort": 3389, + "backendPort": 3389 + } + ] + }, + "outboundRules": { + "value": [ + { + "name": "outboundRule1", + "frontendIPConfigurationName": "publicIPConfig1", + "backendAddressPoolName": "backendAddressPool1", + "allocatedOutboundPorts": 63984 + } + ] + }, + "probes": { + "value": [ + { + "name": "probe1", + "protocol": "Tcp", + "port": 80, + "intervalInSeconds": 10, + "numberOfProbes": 5 + }, + { + "name": "probe2", + "protocol": "Https", + "port": 443, + "requestPath": "/" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep b/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep new file mode 100644 index 000000000..fa6d17707 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. The name of the parent load balancer') +param loadBalancerName string + +@description('Required. The name of the backend address pool') +param name string + +@description('Optional. An array of backend addresses.') +param loadBalancerBackendAddresses array = [] + +@description('Optional. An array of gateway load balancer tunnel interfaces.') +param tunnelInterfaces array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: loadBalancerName +} + +resource backendAddressPool 'Microsoft.Network/loadBalancers/backendAddressPools@2021-05-01' = { + name: name + properties: { + loadBalancerBackendAddresses: loadBalancerBackendAddresses + tunnelInterfaces: tunnelInterfaces + } + parent: loadBalancer +} + +@description('The name of the backend address pool') +output name string = backendAddressPool.name + +@description('The resource ID of the backend address pool') +output resourceId string = backendAddressPool.id + +@description('The resource group the backend address pool was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/readme.md b/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/readme.md new file mode 100644 index 000000000..ccaebf96f --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/readme.md @@ -0,0 +1,44 @@ +# Load Balancers Backend Address Pools `[Microsoft.Network/loadBalancers/backendAddressPools]` + +This module deploys load balancer backend address pools. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/loadBalancers/backendAddressPools` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `loadBalancerName` | string | The name of the parent load balancer | +| `name` | string | The name of the backend address pool | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `loadBalancerBackendAddresses` | array | `[]` | An array of backend addresses. | +| `tunnelInterfaces` | array | `[]` | An array of gateway load balancer tunnel interfaces. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backend address pool | +| `resourceGroupName` | string | The resource group the backend address pool was deployed into | +| `resourceId` | string | The resource ID of the backend address pool | + +## Template references + +- [Loadbalancers/Backendaddresspools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/backendAddressPools) diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/version.json b/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/backendAddressPools/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/carml/1.2.0/Microsoft.Network/loadBalancers/deploy.bicep b/carml/1.2.0/Microsoft.Network/loadBalancers/deploy.bicep new file mode 100644 index 000000000..bb467080b --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/deploy.bicep @@ -0,0 +1,268 @@ +@description('Required. The Proximity Placement Groups Name') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Name of a load balancer SKU.') +@allowed([ + 'Basic' + 'Standard' +]) +param loadBalancerSku string = 'Standard' + +@description('Required. Array of objects containing all frontend IP configurations') +@minLength(1) +param frontendIPConfigurations array + +@description('Optional. Collection of backend address pools used by a load balancer.') +param backendAddressPools array = [] + +@description('Optional. Array of objects containing all load balancing rules') +param loadBalancingRules array = [] + +@description('Optional. Array of objects containing all probes, these are references in the load balancing rules') +param probes array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Collection of inbound NAT Rules used by a load balancer. Defining inbound NAT rules on your load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. They have to reference individual inbound NAT rules.') +param inboundNatRules array = [] + +@description('Optional. The outbound rules.') +param outboundRules array = [] + +var frontendIPConfigurations_var = [for (frontendIPConfiguration, index) in frontendIPConfigurations: { + name: frontendIPConfiguration.name + properties: { + subnet: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) ? { + id: frontendIPConfiguration.subnetId + } : null + publicIPAddress: contains(frontendIPConfiguration, 'publicIPAddressId') && !empty(frontendIPConfiguration.publicIPAddressId) ? { + id: frontendIPConfiguration.publicIPAddressId + } : null + privateIPAddress: contains(frontendIPConfiguration, 'privateIPAddress') && !empty(frontendIPConfiguration.privateIPAddress) ? frontendIPConfiguration.privateIPAddress : null + privateIPAddressVersion: contains(frontendIPConfiguration, 'privateIPAddressVersion') ? frontendIPConfiguration.privateIPAddressVersion : 'IPv4' + privateIPAllocationMethod: contains(frontendIPConfiguration, 'subnetId') && !empty(frontendIPConfiguration.subnetId) ? (contains(frontendIPConfiguration, 'privateIPAddress') ? 'Static' : 'Dynamic') : null + gatewayLoadBalancer: contains(frontendIPConfiguration, 'gatewayLoadBalancer') && !empty(frontendIPConfiguration.gatewayLoadBalancer) ? { + id: frontendIPConfiguration.gatewayLoadBalancer + } : null + publicIPPrefix: contains(frontendIPConfiguration, 'publicIPPrefix') && !empty(frontendIPConfiguration.publicIPPrefix) ? { + id: frontendIPConfiguration.publicIPPrefix + } : null + } +}] + +var loadBalancingRules_var = [for loadBalancingRule in loadBalancingRules: { + name: loadBalancingRule.name + properties: { + backendAddressPool: { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, loadBalancingRule.backendAddressPoolName) + } + backendPort: loadBalancingRule.backendPort + disableOutboundSnat: contains(loadBalancingRule, 'disableOutboundSnat') ? loadBalancingRule.disableOutboundSnat : true + enableFloatingIP: contains(loadBalancingRule, 'enableFloatingIP') ? loadBalancingRule.enableFloatingIP : false + enableTcpReset: contains(loadBalancingRule, 'enableTcpReset') ? loadBalancingRule.enableTcpReset : false + frontendIPConfiguration: { + id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, loadBalancingRule.frontendIPConfigurationName) + } + frontendPort: loadBalancingRule.frontendPort + idleTimeoutInMinutes: contains(loadBalancingRule, 'idleTimeoutInMinutes') ? loadBalancingRule.idleTimeoutInMinutes : 4 + loadDistribution: contains(loadBalancingRule, 'loadDistribution') ? loadBalancingRule.loadDistribution : 'Default' + probe: { + id: '${az.resourceId('Microsoft.Network/loadBalancers', name)}/probes/${loadBalancingRule.probeName}' + } + protocol: contains(loadBalancingRule, 'protocol') ? loadBalancingRule.protocol : 'Tcp' + } +}] + +var outboundRules_var = [for outboundRule in outboundRules: { + name: outboundRule.name + properties: { + frontendIPConfigurations: [ + { + id: az.resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', name, outboundRule.frontendIPConfigurationName) + } + ] + backendAddressPool: { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, outboundRule.backendAddressPoolName) + } + protocol: contains(outboundRule, 'protocol') ? outboundRule.protocol : 'All' + allocatedOutboundPorts: contains(outboundRule, 'allocatedOutboundPorts') ? outboundRule.allocatedOutboundPorts : 63984 + enableTcpReset: contains(outboundRule, 'enableTcpReset') ? outboundRule.enableTcpReset : true + idleTimeoutInMinutes: contains(outboundRule, 'idleTimeoutInMinutes') ? outboundRule.idleTimeoutInMinutes : 4 + } +}] + +var probes_var = [for probe in probes: { + name: probe.name + properties: { + protocol: contains(probe, 'protocol') ? probe.protocol : 'Tcp' + requestPath: toLower(probe.protocol) != 'tcp' ? probe.requestPath : null + port: contains(probe, 'port') ? probe.port : 80 + intervalInSeconds: contains(probe, 'intervalInSeconds') ? probe.intervalInSeconds : 5 + numberOfProbes: contains(probe, 'numberOfProbes') ? probe.numberOfProbes : 2 + } +}] + +var backendAddressPoolNames = [for backendAddressPool in backendAddressPools: { + name: backendAddressPool.name +}] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: loadBalancerSku + } + properties: { + frontendIPConfigurations: frontendIPConfigurations_var + loadBalancingRules: loadBalancingRules_var + backendAddressPools: backendAddressPoolNames + outboundRules: outboundRules_var + probes: probes_var + } +} + +module loadBalancer_backendAddressPools 'backendAddressPools/deploy.bicep' = [for (backendAddressPool, index) in backendAddressPools: { + name: '${uniqueString(deployment().name, location)}-loadBalancer-backendAddressPools-${index}' + params: { + loadBalancerName: loadBalancer.name + name: backendAddressPool.name + tunnelInterfaces: contains(backendAddressPool, 'tunnelInterfaces') && !empty(backendAddressPool.tunnelInterfaces) ? backendAddressPool.tunnelInterfaces : [] + loadBalancerBackendAddresses: contains(backendAddressPool, 'loadBalancerBackendAddresses') && !empty(backendAddressPool.loadBalancerBackendAddresses) ? backendAddressPool.loadBalancerBackendAddresses : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module loadBalancer_inboundNATRules 'inboundNatRules/deploy.bicep' = [for (inboundNATRule, index) in inboundNatRules: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-inboundNatRules-${index}' + params: { + loadBalancerName: loadBalancer.name + name: inboundNATRule.name + frontendIPConfigurationName: inboundNATRule.frontendIPConfigurationName + frontendPort: inboundNATRule.frontendPort + backendPort: contains(inboundNATRule, 'backendPort') ? inboundNATRule.backendPort : inboundNATRule.frontendPort + backendAddressPoolName: contains(inboundNATRule, 'backendAddressPoolName') ? inboundNATRule.backendAddressPoolName : '' + enableFloatingIP: contains(inboundNATRule, 'enableFloatingIP') ? inboundNATRule.enableFloatingIP : false + enableTcpReset: contains(inboundNATRule, 'enableTcpReset') ? inboundNATRule.enableTcpReset : false + frontendPortRangeEnd: contains(inboundNATRule, 'frontendPortRangeEnd') ? inboundNATRule.frontendPortRangeEnd : -1 + frontendPortRangeStart: contains(inboundNATRule, 'frontendPortRangeStart') ? inboundNATRule.frontendPortRangeStart : -1 + idleTimeoutInMinutes: contains(inboundNATRule, 'idleTimeoutInMinutes') ? inboundNATRule.idleTimeoutInMinutes : 4 + protocol: contains(inboundNATRule, 'protocol') ? inboundNATRule.protocol : 'Tcp' + enableDefaultTelemetry: enableDefaultTelemetry + } + dependsOn: [ + loadBalancer_backendAddressPools + ] +}] + +resource loadBalancer_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${loadBalancer.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: loadBalancer +} + +resource loadBalancer_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: loadBalancer +} + +module loadBalancer_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LoadBalancer-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: loadBalancer.id + } +}] + +@description('The name of the load balancer') +output name string = loadBalancer.name + +@description('The resource ID of the load balancer') +output resourceId string = loadBalancer.id + +@description('The resource group the load balancer was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The backend address pools available in the load balancer.') +output backendpools array = loadBalancer.properties.backendAddressPools diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep b/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep new file mode 100644 index 000000000..1722a0f57 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/deploy.bicep @@ -0,0 +1,97 @@ +@description('Required. The name of the parent load balancer') +param loadBalancerName string + +@description('Required. The name of the inbound NAT rule') +param name string + +@description('Required. The port for the external endpoint. Port numbers for each rule must be unique within the Load Balancer. ') +@minValue(1) +@maxValue(65534) +param frontendPort int + +@description('Optional. The port used for the internal endpoint.') +@minValue(1) +@maxValue(65535) +param backendPort int = frontendPort + +@description('Optional. Name of the backend address pool') +param backendAddressPoolName string = '' + +@description('Optional. Configures a virtual machine\'s endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. This setting can\'t be changed after you create the endpoint.') +param enableFloatingIP bool = false + +@description('Optional. Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. This element is only used when the protocol is set to TCP.') +param enableTcpReset bool = false + +@description('Required. The name of the frontend IP address to set for the inbound NAT rule') +param frontendIPConfigurationName string + +@description('Optional. The port range end for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeStart. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool.') +@minValue(-1) +@maxValue(65534) +param frontendPortRangeEnd int = -1 + +@description('Optional. The port range start for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeEnd. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool.') +@minValue(-1) +@maxValue(65534) +param frontendPortRangeStart int = -1 + +@description('Optional. The timeout for the TCP idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP.') +param idleTimeoutInMinutes int = 4 + +@description('Optional. The transport protocol for the endpoint.') +@allowed([ + 'All' + 'Tcp' + 'Udp' +]) +param protocol string = 'Tcp' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2021-05-01' existing = { + name: loadBalancerName +} + +resource inboundNatRule 'Microsoft.Network/loadBalancers/inboundNatRules@2021-05-01' = { + name: name + properties: { + frontendPort: frontendPort + backendPort: backendPort + backendAddressPool: !empty(backendAddressPoolName) ? { + id: az.resourceId('Microsoft.Network/loadBalancers/backendAddressPools', name, backendAddressPoolName) + } : null + enableFloatingIP: enableFloatingIP + enableTcpReset: enableTcpReset + frontendIPConfiguration: { + id: '${loadBalancer.id}/frontendIPConfigurations/${frontendIPConfigurationName}' + } + frontendPortRangeStart: frontendPortRangeStart != -1 ? frontendPortRangeStart : null + frontendPortRangeEnd: frontendPortRangeEnd != -1 ? frontendPortRangeEnd : null + idleTimeoutInMinutes: idleTimeoutInMinutes + protocol: protocol + } + parent: loadBalancer +} + +@description('The name of the inbound NAT rule') +output name string = inboundNatRule.name + +@description('The resource ID of the inbound NAT rule') +output resourceId string = inboundNatRule.id + +@description('The resource group the inbound NAT rule was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/readme.md b/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/readme.md new file mode 100644 index 000000000..00e271ae0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/readme.md @@ -0,0 +1,52 @@ +# Load Balancer Inbound NAT Rules `[Microsoft.Network/loadBalancers/inboundNatRules]` + +This module deploys load balancers inbound NAT rules. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/loadBalancers/inboundNatRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `frontendIPConfigurationName` | string | The name of the frontend IP address to set for the inbound NAT rule | +| `frontendPort` | int | The port for the external endpoint. Port numbers for each rule must be unique within the Load Balancer. | +| `loadBalancerName` | string | The name of the parent load balancer | +| `name` | string | The name of the inbound NAT rule | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backendAddressPoolName` | string | `''` | | Name of the backend address pool | +| `backendPort` | int | `[parameters('frontendPort')]` | | The port used for the internal endpoint. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableFloatingIP` | bool | `False` | | Configures a virtual machine's endpoint for the floating IP capability required to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn Availability Groups in SQL server. This setting can't be changed after you create the endpoint. | +| `enableTcpReset` | bool | `False` | | Receive bidirectional TCP Reset on TCP flow idle timeout or unexpected connection termination. This element is only used when the protocol is set to TCP. | +| `frontendPortRangeEnd` | int | `-1` | | The port range end for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeStart. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool. | +| `frontendPortRangeStart` | int | `-1` | | The port range start for the external endpoint. This property is used together with BackendAddressPool and FrontendPortRangeEnd. Individual inbound NAT rule port mappings will be created for each backend address from BackendAddressPool. | +| `idleTimeoutInMinutes` | int | `4` | | The timeout for the TCP idle connection. The value can be set between 4 and 30 minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP. | +| `protocol` | string | `'Tcp'` | `[All, Tcp, Udp]` | The transport protocol for the endpoint. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the inbound NAT rule | +| `resourceGroupName` | string | The resource group the inbound NAT rule was deployed into | +| `resourceId` | string | The resource ID of the inbound NAT rule | + +## Template references + +- [Loadbalancers/Inboundnatrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/inboundNatRules) diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/version.json b/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/inboundNatRules/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/carml/1.2.0/Microsoft.Network/loadBalancers/readme.md b/carml/1.2.0/Microsoft.Network/loadBalancers/readme.md new file mode 100644 index 000000000..2da63f315 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/readme.md @@ -0,0 +1,243 @@ +# Load Balancers `[Microsoft.Network/loadBalancers]` + +This module deploys a load balancer. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/loadBalancers` | 2021-05-01 | +| `Microsoft.Network/loadBalancers/backendAddressPools` | 2021-05-01 | +| `Microsoft.Network/loadBalancers/inboundNatRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `frontendIPConfigurations` | array | Array of objects containing all frontend IP configurations | +| `name` | string | The Proximity Placement Groups Name | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `backendAddressPools` | _[backendAddressPools](backendAddressPools/readme.md)_ array | `[]` | | Collection of backend address pools used by a load balancer. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `inboundNatRules` | _[inboundNatRules](inboundNatRules/readme.md)_ array | `[]` | | Collection of inbound NAT Rules used by a load balancer. Defining inbound NAT rules on your load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an Inbound NAT pool. They have to reference individual inbound NAT rules. | +| `loadBalancerSku` | string | `'Standard'` | `[Basic, Standard]` | Name of a load balancer SKU. | +| `loadBalancingRules` | array | `[]` | | Array of objects containing all load balancing rules | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `outboundRules` | array | `[]` | | The outbound rules. | +| `probes` | array | `[]` | | Array of objects containing all probes, these are references in the load balancing rules | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `frontendIPConfigurations` + +```json +"frontendIPConfigurations": { + "value": [ + { + "name": "p_hub-bfw-server-feip", + "properties": { + "publicIPAddressId": "[reference(variables('deploymentPIP-VPN')).outputs.publicIPAddressResourceId.value]", + "subnetId": "", + "privateIPAddress": "" + } + } + ] +} +``` + +### Parameter Usage: `backendAddressPools` + +```json +"backendAddressPools": { + "value": [ + { + "name": "p_hub-bfw-server-bepool", + "properties": { + "loadBalancerBackendAddresses": [ + { + "name": "iacs-sh-main-pd-01-euw-rg-network_awefwa01p-nic-int-01ipconfig-internal", + "properties": { + "virtualNetwork": { + "id": "[reference(variables('deploymentVNET')).outputs.vNetResourceId.value]" + }, + "ipAddress": "172.22.232.5" + } + }, + { + "name": "iacs-sh-main-pd-01-euw-rg-network_awefwa01p-ha-nic-int-01ipconfig-internal", + "properties": { + "virtualNetwork": { + "id": "[reference(variables('deploymentVNET')).outputs.vNetResourceId.value]" + }, + "ipAddress": "172.22.232.6" + } + } + ] + } + } + ] +} +``` + +### Parameter Usage: `loadBalancingRules` + +```json +"loadBalancingRules": { +"value": [ + { + "name": "p_hub-bfw-server-IPSEC-IKE-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 500, + "backendPort": 500, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-IPSEC-NATT-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 4500, + "backendPort": 4500, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-TINA-UDP-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Udp", + "frontendPort": 691, + "backendPort": 691, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + }, + { + "name": "p_hub-bfw-server-TINA-TCP-lbrule", + "properties": { + "frontendIPConfigurationName": "p_hub-bfw-server-feip", + "backendAddressPoolName": "p_hub-bfw-server-bepool", + "protocol": "Tcp", + "frontendPort": 691, + "backendPort": 691, + "enableFloatingIP": false, + "idleTimeoutInMinutes": 5, + "probeName": "p_hub-bfw-server-tcp-65001-probe" + } + } +] +} +``` + +### Parameter Usage: `probes` + +```json +"probes": { + "value": [ + { + "name": "p_hub-bfw-server-tcp-65001-probe", + "properties": { + "protocol": "Tcp", + "port": 65001, + "intervalInSeconds": 5, + "numberOfProbes": 2 + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `backendpools` | array | The backend address pools available in the load balancer. | +| `name` | string | The name of the load balancer | +| `resourceGroupName` | string | The resource group the load balancer was deployed into | +| `resourceId` | string | The resource ID of the load balancer | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Loadbalancers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers) +- [Loadbalancers/Backendaddresspools](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/backendAddressPools) +- [Loadbalancers/Inboundnatrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/loadBalancers/inboundNatRules) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/loadBalancers/version.json b/carml/1.2.0/Microsoft.Network/loadBalancers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/loadBalancers/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/carml/1.2.0/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..621a3ee40 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/localNetworkGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(localNetworkGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: localNetworkGateway +}] diff --git a/carml/1.2.0/Microsoft.Network/localNetworkGateways/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/localNetworkGateways/.parameters/parameters.json new file mode 100644 index 000000000..878777fb1 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/localNetworkGateways/.parameters/parameters.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-lng-x-001" + }, + "localAddressPrefixes": { + "value": [ + "192.168.1.0/24" + ] + }, + "localGatewayPublicIpAddress": { + "value": "8.8.8.8" + }, + "localAsn": { + "value": "65123" + }, + "localBgpPeeringAddress": { + "value": "192.168.1.5" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/localNetworkGateways/deploy.bicep b/carml/1.2.0/Microsoft.Network/localNetworkGateways/deploy.bicep new file mode 100644 index 000000000..a8570e13a --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/localNetworkGateways/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. Name of the Local Network Gateway') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. List of the local (on-premises) IP address ranges') +param localAddressPrefixes array + +@description('Required. Public IP of the local gateway') +param localGatewayPublicIpAddress string + +@description('Optional. The BGP speaker\'s ASN. Not providing this value will automatically disable BGP on this Local Network Gateway resource.') +param localAsn string = '' + +@description('Optional. The BGP peering address and BGP identifier of this BGP speaker. Not providing this value will automatically disable BGP on this Local Network Gateway resource.') +param localBgpPeeringAddress string = '' + +@description('Optional. The weight added to routes learned from this BGP speaker. This will only take effect if both the localAsn and the localBgpPeeringAddress values are provided.') +param localPeerWeight string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. FQDN of local network gateway.') +param fqdn string = '' + +var bgpSettings = { + asn: localAsn + bgpPeeringAddress: localBgpPeeringAddress + peerWeight: !empty(localPeerWeight) ? localPeerWeight : '0' +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2021-08-01' = { + name: name + location: location + tags: tags + properties: { + localNetworkAddressSpace: { + addressPrefixes: localAddressPrefixes + } + fqdn: !empty(fqdn) ? fqdn : null + gatewayIpAddress: localGatewayPublicIpAddress + bgpSettings: !empty(localAsn) && !empty(localBgpPeeringAddress) ? bgpSettings : null + } +} + +resource localNetworkGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${localNetworkGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: localNetworkGateway +} + +module localNetworkGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-LocalNetworkGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: localNetworkGateway.id + } +}] + +@description('The resource ID of the local network gateway') +output resourceId string = localNetworkGateway.id + +@description('The resource group the local network gateway was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the local network gateway') +output name string = localNetworkGateway.name diff --git a/carml/1.2.0/Microsoft.Network/localNetworkGateways/readme.md b/carml/1.2.0/Microsoft.Network/localNetworkGateways/readme.md new file mode 100644 index 000000000..1b9ab9d57 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/localNetworkGateways/readme.md @@ -0,0 +1,98 @@ +# Local Network Gateways `[Microsoft.Network/localNetworkGateways]` + +This module deploys a local network gateway. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/localNetworkGateways` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `localAddressPrefixes` | array | List of the local (on-premises) IP address ranges | +| `localGatewayPublicIpAddress` | string | Public IP of the local gateway | +| `name` | string | Name of the Local Network Gateway | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `fqdn` | string | `''` | | FQDN of local network gateway. | +| `localAsn` | string | `''` | | The BGP speaker's ASN. Not providing this value will automatically disable BGP on this Local Network Gateway resource. | +| `localBgpPeeringAddress` | string | `''` | | The BGP peering address and BGP identifier of this BGP speaker. Not providing this value will automatically disable BGP on this Local Network Gateway resource. | +| `localPeerWeight` | string | `''` | | The weight added to routes learned from this BGP speaker. This will only take effect if both the localAsn and the localBgpPeeringAddress values are provided. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the local network gateway | +| `resourceGroupName` | string | The resource group the local network gateway was deployed into | +| `resourceId` | string | The resource ID of the local network gateway | + +## Template references + +- [Localnetworkgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/localNetworkGateways) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/localNetworkGateways/version.json b/carml/1.2.0/Microsoft.Network/localNetworkGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/localNetworkGateways/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/carml/1.2.0/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5c200476b --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/natGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(natGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: natGateway +}] diff --git a/carml/1.2.0/Microsoft.Network/natGateways/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/natGateways/.parameters/parameters.json new file mode 100644 index 000000000..6f5ac729c --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/natGateways/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-ngw-x-001" + }, + "natGatewayPublicIpAddress": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/natGateways/deploy.bicep b/carml/1.2.0/Microsoft.Network/natGateways/deploy.bicep new file mode 100644 index 000000000..e13ac102e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/natGateways/deploy.bicep @@ -0,0 +1,214 @@ +@description('Required. Name of the Azure Bastion resource') +param name string + +@description('Optional. The idle timeout of the nat gateway.') +param idleTimeoutInMinutes int = 5 + +@description('Optional. Use to have a new Public IP Address created for the NAT Gateway.') +param natGatewayPublicIpAddress bool = false + +@description('Optional. Specifies the name of the Public IP used by the NAT Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the Bastion\'s name.') +param natGatewayPipName string = '' + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param natGatewayPublicIPPrefixId string = '' + +@description('Optional. DNS name of the Public IP resource. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com') +param natGatewayDomainNameLabel string = '' + +@description('Optional. Existing Public IP Address resource names to use for the NAT Gateway.') +param publicIpAddresses array = [] + +@description('Optional. Existing Public IP Prefixes resource names to use for the NAT Gateway.') +param publicIpPrefixes array = [] + +@description('Optional. A list of availability zones denoting the zone in which Nat Gateway should be deployed.') +param zones array = [] + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags for the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var natGatewayPipName_var = (empty(natGatewayPipName) ? '${name}-pip' : natGatewayPipName) +var natGatewayPublicIPPrefix = { + id: natGatewayPublicIPPrefixId +} + +var natGatewayPropertyPublicIPPrefixes = [for publicIpPrefix in publicIpPrefixes: { + id: az.resourceId('Microsoft.Network/publicIPPrefixes', publicIpPrefix) +}] +var natGatewayPropertyPublicIPAddresses = [for publicIpAddress in publicIpAddresses: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', publicIpAddress) +}] +var natGatewayProperties = { + idleTimeoutInMinutes: idleTimeoutInMinutes + publicIpPrefixes: natGatewayPropertyPublicIPPrefixes + publicIpAddresses: natGatewayPropertyPublicIPAddresses +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +// PUBLIC IP +// ========= +resource publicIP 'Microsoft.Network/publicIPAddresses@2021-05-01' = if (natGatewayPublicIpAddress) { + name: natGatewayPipName_var + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: { + publicIPAllocationMethod: 'Static' + publicIPPrefix: !empty(natGatewayPublicIPPrefixId) ? natGatewayPublicIPPrefix : null + dnsSettings: !empty(natGatewayDomainNameLabel) ? json('{"domainNameLabel": "${natGatewayDomainNameLabel}"}') : null + } +} + +resource publicIP_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIP.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIP +} + +resource publicIP_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIP +} + +// NAT GATEWAY +// =========== +resource natGateway 'Microsoft.Network/natGateways@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: natGatewayProperties + zones: zones +} + +resource natGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${natGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: natGateway +} + +module natGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NatGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: natGateway.id + } +}] + +@description('The name of the NAT Gateway') +output name string = natGateway.name + +@description('The resource ID of the NAT Gateway') +output resourceId string = natGateway.id + +@description('The resource group the NAT Gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/natGateways/readme.md b/carml/1.2.0/Microsoft.Network/natGateways/readme.md new file mode 100644 index 000000000..309734fea --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/natGateways/readme.md @@ -0,0 +1,112 @@ +# NAT Gateways `[Microsoft.Network/natGateways]` + +This module deploys a NAT gateway. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/natGateways` | 2021-05-01 | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Azure Bastion resource | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `idleTimeoutInMinutes` | int | `5` | | The idle timeout of the nat gateway. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `natGatewayDomainNameLabel` | string | `''` | | DNS name of the Public IP resource. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com | +| `natGatewayPipName` | string | `''` | | Specifies the name of the Public IP used by the NAT Gateway. If it's not provided, a '-pip' suffix will be appended to the Bastion's name. | +| `natGatewayPublicIpAddress` | bool | `False` | | Use to have a new Public IP Address created for the NAT Gateway. | +| `natGatewayPublicIPPrefixId` | string | `''` | | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `publicIpAddresses` | array | `[]` | | Existing Public IP Address resource names to use for the NAT Gateway. | +| `publicIpPrefixes` | array | `[]` | | Existing Public IP Prefixes resource names to use for the NAT Gateway. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags for the resource. | +| `zones` | array | `[]` | | A list of availability zones denoting the zone in which Nat Gateway should be deployed. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT Gateway | +| `resourceGroupName` | string | The resource group the NAT Gateway was deployed into | +| `resourceId` | string | The resource ID of the NAT Gateway | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Natgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/natGateways) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/natGateways/version.json b/carml/1.2.0/Microsoft.Network/natGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/natGateways/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/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..3e691d4ae --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,58 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkSecurityGroup.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: networkSecurityGroup +}] diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.parameters/min.parameters.json new file mode 100644 index 000000000..b07946467 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-nsg-min-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json new file mode 100644 index 000000000..c8f75d3aa --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/.parameters/parameters.json @@ -0,0 +1,100 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-nsg-x-001" + }, + "securityRules": { + "value": [ + { + "name": "Specific", + "properties": { + "description": "Tests specific IPs and ports", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8080", + "sourceAddressPrefix": "*", + "destinationAddressPrefix": "*", + "access": "Allow", + "priority": 100, + "direction": "Inbound" + } + }, + { + "name": "Ranges", + "properties": { + "description": "Tests Ranges", + "protocol": "*", + "access": "Allow", + "priority": 101, + "direction": "Inbound", + "sourcePortRanges": [ + "80", + "81" + ], + "destinationPortRanges": [ + "90", + "91" + ], + "sourceAddressPrefixes": [ + "10.0.0.0/16", + "10.1.0.0/16" + ], + "destinationAddressPrefixes": [ + "10.2.0.0/16", + "10.3.0.0/16" + ] + } + }, + { + "name": "Port_8082", + "properties": { + "description": "Allow inbound access on TCP 8082", + "protocol": "*", + "sourcePortRange": "*", + "destinationPortRange": "8082", + "access": "Allow", + "priority": 102, + "direction": "Inbound", + "sourceApplicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ], + "destinationApplicationSecurityGroups": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + } + ] + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/deploy.bicep b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/deploy.bicep new file mode 100644 index 000000000..5db5c2fce --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/deploy.bicep @@ -0,0 +1,169 @@ +@description('Required. Name of the Network Security Group.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed.') +param securityRules array = [] + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the NSG resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +]) +param diagnosticLogCategoriesToEnable array = [ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + securityRules: [for securityRule in securityRules: { + name: securityRule.name + properties: { + protocol: securityRule.properties.protocol + access: securityRule.properties.access + priority: securityRule.properties.priority + direction: securityRule.properties.direction + description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' + sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : '' + sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : [] + destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : '' + destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : [] + sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : '' + destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : '' + sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : [] + destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : [] + sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : [] + destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : [] + } + }] + } +} + +module networkSecurityGroup_securityRules 'securityRules/deploy.bicep' = [for (securityRule, index) in securityRules: { + name: '${uniqueString(deployment().name, location)}-securityRule-${index}' + params: { + name: securityRule.name + networkSecurityGroupName: networkSecurityGroup.name + protocol: securityRule.properties.protocol + access: securityRule.properties.access + priority: securityRule.properties.priority + direction: securityRule.properties.direction + description: contains(securityRule.properties, 'description') ? securityRule.properties.description : '' + sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : '' + sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : [] + destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : '' + destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : [] + sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : '' + destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : '' + sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : [] + destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : [] + sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : [] + destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +resource networkSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkSecurityGroup.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkSecurityGroup +} + +resource networkSecurityGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + logs: diagnosticsLogs + } + scope: networkSecurityGroup +} + +module networkSecurityGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NSG-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkSecurityGroup.id + } +}] + +@description('The resource group the network security group was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the network security group') +output resourceId string = networkSecurityGroup.id + +@description('The name of the network security group') +output name string = networkSecurityGroup.name diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/readme.md b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/readme.md new file mode 100644 index 000000000..4272efbf6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/readme.md @@ -0,0 +1,104 @@ +# Network Security Groups `[Microsoft.Network/networkSecurityGroups]` + +This template deploys a network security group (NSG) with optional security rules. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/networkSecurityGroups` | 2021-05-01 | +| `Microsoft.Network/networkSecurityGroups/securityRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Network Security Group. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `securityRules` | _[securityRules](securityRules/readme.md)_ array | `[]` | | Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed. | +| `tags` | object | `{object}` | | Tags of the NSG resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the network security group | +| `resourceGroupName` | string | The resource group the network security group was deployed into | +| `resourceId` | string | The resource ID of the network security group | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networksecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups) +- [Networksecuritygroups/Securityrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups/securityRules) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/deploy.bicep b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/deploy.bicep new file mode 100644 index 000000000..62f7a6e7d --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/deploy.bicep @@ -0,0 +1,117 @@ +@sys.description('Required. The name of the security rule') +param name string + +@sys.description('Required. The name of the network security group to deploy the security rule into') +param networkSecurityGroupName string + +@sys.description('Optional. Whether network traffic is allowed or denied.') +@allowed([ + 'Allow' + 'Deny' +]) +param access string = 'Deny' + +@sys.description('Optional. A description for this rule') +@maxLength(140) +param description string = '' + +@sys.description('Optional. The destination address prefix. CIDR or destination IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used.') +param destinationAddressPrefix string = '' + +@sys.description('Optional. The destination address prefixes. CIDR or destination IP ranges.') +param destinationAddressPrefixes array = [] + +@sys.description('Optional. The application security group specified as destination.') +param destinationApplicationSecurityGroups array = [] + +@sys.description('Optional. The destination port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports.') +param destinationPortRange string = '' + +@sys.description('Optional. The destination port ranges.') +param destinationPortRanges array = [] + +@sys.description('Required. The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic.') +@allowed([ + 'Inbound' + 'Outbound' +]) +param direction string + +@sys.description('Required. The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule.') +param priority int + +@sys.description('Required. Network protocol this rule applies to.') +@allowed([ + '*' + 'Ah' + 'Esp' + 'Icmp' + 'Tcp' + 'Udp' +]) +param protocol string + +@sys.description('Optional. The CIDR or source IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. If this is an ingress rule, specifies where network traffic originates from.') +param sourceAddressPrefix string = '' + +@sys.description('Optional. The CIDR or source IP ranges.') +param sourceAddressPrefixes array = [] + +@sys.description('Optional. The application security group specified as source.') +param sourceApplicationSecurityGroups array = [] + +@sys.description('Optional. The source port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports.') +param sourcePortRange string = '' + +@sys.description('Optional. The source port ranges.') +param sourcePortRanges array = [] + +@sys.description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = { + name: networkSecurityGroupName +} + +resource securityRule 'Microsoft.Network/networkSecurityGroups/securityRules@2021-05-01' = { + name: name + parent: networkSecurityGroup + properties: { + access: access + description: description + destinationAddressPrefix: destinationAddressPrefix + destinationAddressPrefixes: destinationAddressPrefixes + destinationApplicationSecurityGroups: destinationApplicationSecurityGroups + destinationPortRange: destinationPortRange + destinationPortRanges: destinationPortRanges + direction: direction + priority: priority + protocol: protocol + sourceAddressPrefix: sourceAddressPrefix + sourceAddressPrefixes: sourceAddressPrefixes + sourceApplicationSecurityGroups: sourceApplicationSecurityGroups + sourcePortRange: sourcePortRange + sourcePortRanges: sourcePortRanges + } +} + +@sys.description('The resource group the security rule was deployed into') +output resourceGroupName string = resourceGroup().name + +@sys.description('The resource ID of the security rule') +output resourceId string = securityRule.id + +@sys.description('The name of the security rule') +output name string = securityRule.name diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/readme.md b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/readme.md new file mode 100644 index 000000000..2cbeb3eea --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/readme.md @@ -0,0 +1,57 @@ +# Network Security Groups Security Rules `[Microsoft.Network/networkSecurityGroups/securityRules]` + +This module deploys Network Security Group Security Rules. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkSecurityGroups/securityRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `direction` | string | `[Inbound, Outbound]` | The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic. | +| `name` | string | | The name of the security rule | +| `networkSecurityGroupName` | string | | The name of the network security group to deploy the security rule into | +| `priority` | int | | The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule. | +| `protocol` | string | `[*, Ah, Esp, Icmp, Tcp, Udp]` | Network protocol this rule applies to. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `access` | string | `'Deny'` | `[Allow, Deny]` | Whether network traffic is allowed or denied. | +| `description` | string | `''` | | A description for this rule | +| `destinationAddressPrefix` | string | `''` | | The destination address prefix. CIDR or destination IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. | +| `destinationAddressPrefixes` | array | `[]` | | The destination address prefixes. CIDR or destination IP ranges. | +| `destinationApplicationSecurityGroups` | array | `[]` | | The application security group specified as destination. | +| `destinationPortRange` | string | `''` | | The destination port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports. | +| `destinationPortRanges` | array | `[]` | | The destination port ranges. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `sourceAddressPrefix` | string | `''` | | The CIDR or source IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. If this is an ingress rule, specifies where network traffic originates from. | +| `sourceAddressPrefixes` | array | `[]` | | The CIDR or source IP ranges. | +| `sourceApplicationSecurityGroups` | array | `[]` | | The application security group specified as source. | +| `sourcePortRange` | string | `''` | | The source port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports. | +| `sourcePortRanges` | array | `[]` | | The source port ranges. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the security rule | +| `resourceGroupName` | string | The resource group the security rule was deployed into | +| `resourceId` | string | The resource ID of the security rule | + +## Template references + +- [Networksecuritygroups/Securityrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups/securityRules) diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/version.json b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/securityRules/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Network/networkSecurityGroups/version.json b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkSecurityGroups/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/carml/1.2.0/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..8d685ea44 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(networkWatcher.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: networkWatcher +}] diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/networkWatchers/.parameters/min.parameters.json new file mode 100644 index 000000000..78acbb0c7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "value": "northeurope" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/networkWatchers/.parameters/parameters.json new file mode 100644 index 000000000..78a7e1f27 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/.parameters/parameters.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "adp-<>-az-nw-x-001" + }, + "flowLogs": { + "value": [ + { + "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "enabled": false + }, + { + "name": "adp-<>-az-nsg-x-apgw-flowlog", + "targetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-apgw", + "storageId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "formatVersion": 1, + "trafficAnalyticsInterval": 10, + "retentionInDays": 8 + } + ] + }, + "connectionMonitors": { + "value": [ + { + "name": "adp-<>-az-conn-mon-x-001", + "endpoints": [ + { + "name": "<>-az-subnet-x-001(validation-rg)", + "type": "AzureVM", + "resourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/virtualMachines/adp-<>-vm-01" + }, + { + "name": "Office Portal", + "type": "ExternalAddress", + "address": "www.office.com" + } + ], + "testConfigurations": [ + { + "name": "HTTP Test", + "testFrequencySec": 30, + "protocol": "Http", + "httpConfiguration": { + "port": 80, + "method": "Get", + "requestHeaders": [], + "validStatusCodeRanges": [ + "200" + ], + "preferHTTPS": false + }, + "successThreshold": { + "checksFailedPercent": 5, + "roundTripTimeMs": 100 + } + } + ], + "testGroups": [ + { + "name": "TestHTTPBing", + "disable": false, + "testConfigurations": [ + "HTTP Test" + ], + "sources": [ + "<>-az-subnet-x-001(validation-rg)" + ], + "destinations": [ + "Office Portal" + ] + } + ], + "workspaceResourceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep b/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep new file mode 100644 index 000000000..492ee37c4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/deploy.bicep @@ -0,0 +1,73 @@ +@description('Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG') +param networkWatcherName string = 'NetworkWatcher_${resourceGroup().location}' + +@description('Optional. Name of the resource.') +param name string + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. List of connection monitor endpoints.') +param endpoints array = [] + +@description('Optional. List of connection monitor test configurations.') +param testConfigurations array = [] + +@description('Optional. List of connection monitor test groups.') +param testGroups array = [] + +@description('Optional. Specify the Log Analytics Workspace Resource ID') +param workspaceResourceId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var outputs = !empty(workspaceResourceId) ? [ + { + type: 'Workspace' + workspaceSettings: { + workspaceResourceId: workspaceResourceId + } + } +] : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: networkWatcherName +} + +resource connectionMonitor 'Microsoft.Network/networkWatchers/connectionMonitors@2021-05-01' = { + name: name + parent: networkWatcher + tags: tags + location: location + properties: { + endpoints: endpoints + testConfigurations: testConfigurations + testGroups: testGroups + outputs: outputs + } +} + +@description('The name of the deployed connection monitor') +output name string = connectionMonitor.name + +@description('The resource ID of the deployed connection monitor') +output resourceId string = connectionMonitor.id + +@description('The resource group the connection monitor was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/readme.md b/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/readme.md new file mode 100644 index 000000000..b1d287ba0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/readme.md @@ -0,0 +1,61 @@ +# Network Watchers Connection Monitors `[Microsoft.Network/networkWatchers/connectionMonitors]` + +This template deploys Connection Monitors. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkWatchers/connectionMonitors` | 2021-05-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endpoints` | array | `[]` | List of connection monitor endpoints. | +| `location` | string | `[resourceGroup().location]` | Location for all resources. | +| `name` | string | | Name of the resource. | +| `networkWatcherName` | string | `[format('NetworkWatcher_{0}', resourceGroup().location)]` | Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG | +| `tags` | object | `{object}` | Tags of the resource. | +| `testConfigurations` | array | `[]` | List of connection monitor test configurations. | +| `testGroups` | array | `[]` | List of connection monitor test groups. | +| `workspaceResourceId` | string | `''` | Specify the Log Analytics Workspace Resource ID | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed connection monitor | +| `resourceGroupName` | string | The resource group the connection monitor was deployed into | +| `resourceId` | string | The resource ID of the deployed connection monitor | + +## Template references + +- [Networkwatchers/Connectionmonitors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/connectionMonitors) diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/version.json b/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/connectionMonitors/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/carml/1.2.0/Microsoft.Network/networkWatchers/deploy.bicep b/carml/1.2.0/Microsoft.Network/networkWatchers/deploy.bicep new file mode 100644 index 000000000..8eb5a8a83 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/deploy.bicep @@ -0,0 +1,107 @@ +@description('Required. Name of the Network Watcher resource (hidden)') +@minLength(1) +param name string = 'NetworkWatcher_${location}' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array that contains the Connection Monitors') +param connectionMonitors array = [] + +@description('Optional. Array that contains the Flow Logs') +param flowLogs array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' = { + name: name + location: location + tags: tags + properties: {} +} + +resource networkWatcher_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${networkWatcher.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: networkWatcher +} + +module networkWatcher_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-NW-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: networkWatcher.id + } +}] + +module networkWatcher_connectionMonitors 'connectionMonitors/deploy.bicep' = [for (connectionMonitor, index) in connectionMonitors: { + name: '${uniqueString(deployment().name, location)}-NW-ConnectionMonitor-${index}' + params: { + endpoints: contains(connectionMonitor, 'endpoints') ? connectionMonitor.endpoints : [] + name: connectionMonitor.name + networkWatcherName: networkWatcher.name + testConfigurations: contains(connectionMonitor, 'testConfigurations') ? connectionMonitor.testConfigurations : [] + testGroups: contains(connectionMonitor, 'testGroups') ? connectionMonitor.testGroups : [] + workspaceResourceId: contains(connectionMonitor, 'workspaceResourceId') ? connectionMonitor.workspaceResourceId : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module networkWatcher_flowLogs 'flowLogs/deploy.bicep' = [for (flowLog, index) in flowLogs: { + name: '${uniqueString(deployment().name, location)}-NW-FlowLog-${index}' + params: { + enabled: contains(flowLog, 'enabled') ? flowLog.enabled : true + formatVersion: contains(flowLog, 'formatVersion') ? flowLog.formatVersion : 2 + location: contains(flowLog, 'location') ? flowLog.location : location + name: contains(flowLog, 'name') ? flowLog.name : '${last(split(flowLog.targetResourceId, '/'))}-${split(flowLog.targetResourceId, '/')[4]}-flowlog' + networkWatcherName: networkWatcher.name + retentionInDays: contains(flowLog, 'retentionInDays') ? flowLog.retentionInDays : 365 + storageId: flowLog.storageId + targetResourceId: flowLog.targetResourceId + trafficAnalyticsInterval: contains(flowLog, 'trafficAnalyticsInterval') ? flowLog.trafficAnalyticsInterval : 60 + workspaceResourceId: contains(flowLog, 'workspaceResourceId') ? flowLog.workspaceResourceId : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the deployed network watcher') +output name string = networkWatcher.name + +@description('The resource ID of the deployed network watcher') +output resourceId string = networkWatcher.id + +@description('The resource group the network watcher was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep b/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep new file mode 100644 index 000000000..f148fef06 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/deploy.bicep @@ -0,0 +1,102 @@ +@description('Optional. Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG') +param networkWatcherName string = 'NetworkWatcher_${resourceGroup().location}' + +@description('Optional. Name of the resource.') +param name string = '${last(split(targetResourceId, '/'))}-${split(targetResourceId, '/')[4]}-flowlog' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Resource ID of the NSG that must be enabled for Flow Logs.') +param targetResourceId string + +@description('Required. Resource ID of the diagnostic storage account.') +param storageId string + +@description('Optional. If the flow log should be enabled') +param enabled bool = true + +@description('Optional. The flow log format version') +@allowed([ + 1 + 2 +]) +param formatVersion int = 2 + +@description('Optional. Specify the Log Analytics Workspace Resource ID') +param workspaceResourceId string = '' + +@description('Optional. The interval in minutes which would decide how frequently TA service should do flow analytics.') +@allowed([ + 10 + 60 +]) +param trafficAnalyticsInterval int = 60 + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param retentionInDays int = 365 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var flowAnalyticsConfiguration = !empty(workspaceResourceId) && enabled == true ? { + networkWatcherFlowAnalyticsConfiguration: { + enabled: true + workspaceResourceId: workspaceResourceId + trafficAnalyticsInterval: trafficAnalyticsInterval + } +} : { + networkWatcherFlowAnalyticsConfiguration: { + enabled: false + } +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource networkWatcher 'Microsoft.Network/networkWatchers@2021-05-01' existing = { + name: networkWatcherName +} + +resource flowLog 'Microsoft.Network/networkWatchers/flowLogs@2021-05-01' = { + name: name + parent: networkWatcher + tags: tags + location: location + properties: { + targetResourceId: targetResourceId + storageId: storageId + enabled: enabled + retentionPolicy: { + days: retentionInDays + enabled: retentionInDays == 0 ? false : true + } + format: { + type: 'JSON' + version: formatVersion + } + flowAnalyticsConfiguration: flowAnalyticsConfiguration + } +} +@description('The name of the flow log') +output name string = flowLog.name + +@description('The resource ID of the flow log') +output resourceId string = flowLog.id + +@description('The resource group the flow log was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/readme.md b/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/readme.md new file mode 100644 index 000000000..e7f324bd8 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/readme.md @@ -0,0 +1,69 @@ +# NSG Flow Logs `[Microsoft.Network/networkWatchers/flowLogs]` + +This module controls the Network Security Group Flow Logs and analytics settings +**Note: this module must be run on the Resource Group where Network Watcher is deployed** + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/networkWatchers/flowLogs` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageId` | string | Resource ID of the diagnostic storage account. | +| `targetResourceId` | string | Resource ID of the NSG that must be enabled for Flow Logs. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enabled` | bool | `True` | | If the flow log should be enabled | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `formatVersion` | int | `2` | `[1, 2]` | The flow log format version | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `name` | string | `[format('{0}-{1}-flowlog', last(split(parameters('targetResourceId'), '/')), split(parameters('targetResourceId'), '/')[4])]` | | Name of the resource. | +| `networkWatcherName` | string | `[format('NetworkWatcher_{0}', resourceGroup().location)]` | | Name of the network watcher resource. Must be in the resource group where the Flow log will be created and same region as the NSG | +| `retentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `trafficAnalyticsInterval` | int | `60` | `[10, 60]` | The interval in minutes which would decide how frequently TA service should do flow analytics. | +| `workspaceResourceId` | string | `''` | | Specify the Log Analytics Workspace Resource ID | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the flow log | +| `resourceGroupName` | string | The resource group the flow log was deployed into | +| `resourceId` | string | The resource ID of the flow log | + +## Template references + +- [Networkwatchers/Flowlogs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/flowLogs) diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/version.json b/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/flowLogs/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/carml/1.2.0/Microsoft.Network/networkWatchers/readme.md b/carml/1.2.0/Microsoft.Network/networkWatchers/readme.md new file mode 100644 index 000000000..8e5705d32 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/readme.md @@ -0,0 +1,98 @@ +# Network Watchers `[Microsoft.Network/networkWatchers]` + +This template deploys a network watcher. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/networkWatchers` | 2021-05-01 | +| `Microsoft.Network/networkWatchers/connectionMonitors` | 2021-05-01 | +| `Microsoft.Network/networkWatchers/flowLogs` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `name` | string | `[format('NetworkWatcher_{0}', parameters('location'))]` | Name of the Network Watcher resource (hidden) | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `connectionMonitors` | _[connectionMonitors](connectionMonitors/readme.md)_ array | `[]` | | Array that contains the Connection Monitors | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `flowLogs` | _[flowLogs](flowLogs/readme.md)_ array | `[]` | | Array that contains the Flow Logs | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed network watcher | +| `resourceGroupName` | string | The resource group the network watcher was deployed into | +| `resourceId` | string | The resource ID of the deployed network watcher | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Networkwatchers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers) +- [Networkwatchers/Connectionmonitors](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/connectionMonitors) +- [Networkwatchers/Flowlogs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkWatchers/flowLogs) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/networkWatchers/version.json b/carml/1.2.0/Microsoft.Network/networkWatchers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/networkWatchers/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/carml/1.2.0/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..45993398e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2018-09-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateDnsZone.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: privateDnsZone +}] diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/.parameters/min.parameters.json new file mode 100644 index 000000000..d33fbd032 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-privdns-x-001.com" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/.parameters/parameters.json new file mode 100644 index 000000000..0668e824c --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/.parameters/parameters.json @@ -0,0 +1,139 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-privdns-x-002.com" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "AAAA": { + "value": [ + { + "name": "AAAA_2001_0db8_85a3_0000_0000_8a2e_0370_7334", + "ttl": 3600, + "aaaaRecords": [ + { + "ipv6Address": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + } + ] + } + ] + }, + "A": { + "value": [ + { + "name": "A_10.240.4.4", + "ttl": 3600, + "aRecords": [ + { + "ipv4Address": "10.240.4.4" + } + ] + } + ] + }, + "CNAME": { + "value": [ + { + "name": "CNAME_test", + "ttl": 3600, + "cnameRecord": { + "cname": "test" + } + } + ] + }, + "MX": { + "value": [ + { + "name": "MX_contoso", + "ttl": 3600, + "mxRecords": [ + { + "exchange": "contoso.com", + "preference": 100 + } + ] + } + ] + }, + "PTR": { + "value": [ + { + "name": "PTR_contoso", + "ttl": 3600, + "ptrRecords": [ + { + "ptrdname": "contoso.com" + } + ] + } + ] + }, + "SOA": { + "value": [ + { + "name": "@", + "ttl": 3600, + "soaRecord": { + "email": "azureprivatedns-host.microsoft.com", + "expireTime": 2419200, + "host": "azureprivatedns.net", + "minimumTtl": 10, + "refreshTime": 3600, + "retryTime": 300, + "serialNumber": "1" + } + } + ] + }, + "SRV": { + "value": [ + { + "name": "SRV_contoso", + "ttl": 3600, + "srvRecords": [ + { + "port": 9332, + "priority": 0, + "target": "test.contoso.com", + "weight": 0 + } + ] + } + ] + }, + "TXT": { + "value": [ + { + "name": "TXT_test", + "ttl": 3600, + "txtRecords": [ + { + "value": [ + "test" + ] + } + ] + } + ] + }, + "virtualNetworkLinks": { + "value": [ + { + "virtualNetworkResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001", + "registrationEnabled": true + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/A/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/A/deploy.bicep new file mode 100644 index 000000000..59ead85ae --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/A/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the A record.') +param name string + +@description('Optional. The list of A records in the record set.') +param aRecords array = [] + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource A 'Microsoft.Network/privateDnsZones/A@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + aRecords: aRecords + metadata: metadata + ttl: ttl + } +} + +@description('The name of the deployed A record') +output name string = A.name + +@description('The resource ID of the deployed A record') +output resourceId string = A.id + +@description('The resource group of the deployed A record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/A/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/A/readme.md new file mode 100644 index 000000000..212bca2ad --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/A/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone A record `[Microsoft.Network/privateDnsZones/A]` + +This module deploys a Private DNS Zone A record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/A` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the A record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `aRecords` | array | `[]` | The list of A records in the record set. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `aRecords` + +```json +"aRecords": { + "value": [ + { + "ipv4Address": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed A record | +| `resourceGroupName` | string | The resource group of the deployed A record | +| `resourceId` | string | The resource ID of the deployed A record | + +## Template references + +- [Privatednszones/A](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/A) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/A/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/A/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/A/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/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/deploy.bicep new file mode 100644 index 000000000..1dd9efb23 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the AAAA record.') +param name string + +@description('Optional. The list of AAAA records in the record set.') +param aaaaRecords array = [] + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource AAAA 'Microsoft.Network/privateDnsZones/AAAA@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + aaaaRecords: aaaaRecords + metadata: metadata + ttl: ttl + } +} + +@description('The name of the deployed AAAA record') +output name string = AAAA.name + +@description('The resource ID of the deployed AAAA record') +output resourceId string = AAAA.id + +@description('The resource group of the deployed AAAA record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/readme.md new file mode 100644 index 000000000..566e29d47 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone AAAA record `[Microsoft.Network/privateDnsZones/AAAA]` + +This module deploys a Private DNS Zone AAAA record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/AAAA` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the AAAA record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `aaaaRecords` | array | `[]` | The list of AAAA records in the record set. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `aaaaRecords` + +```json +"aaaaRecords": { + "value": [ + { + "ipv6Address": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed AAAA record | +| `resourceGroupName` | string | The resource group of the deployed AAAA record | +| `resourceId` | string | The resource ID of the deployed AAAA record | + +## Template references + +- [Privatednszones/AAAA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/AAAA) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/AAAA/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/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/deploy.bicep new file mode 100644 index 000000000..680f8d9ab --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the CNAME record.') +param name string + +@description('Optional. A CNAME record.') +param cnameRecord object = {} + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource CNAME 'Microsoft.Network/privateDnsZones/CNAME@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + cnameRecord: cnameRecord + metadata: metadata + ttl: ttl + } +} + +@description('The name of the deployed CNAME record') +output name string = CNAME.name + +@description('The resource ID of the deployed CNAME record') +output resourceId string = CNAME.id + +@description('The resource group of the deployed CNAME record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/readme.md new file mode 100644 index 000000000..665961ea9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/readme.md @@ -0,0 +1,45 @@ +# Private DNS Zone CNAME record `[Microsoft.Network/privateDnsZones/CNAME]` + +This module deploys a Private DNS Zone CNAME record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/CNAME` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the CNAME record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `cnameRecord` | object | `{object}` | A CNAME record. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed CNAME record | +| `resourceGroupName` | string | The resource group of the deployed CNAME record | +| `resourceId` | string | The resource ID of the deployed CNAME record | + +## Template references + +- [Privatednszones/CNAME](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/CNAME) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/CNAME/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/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/deploy.bicep new file mode 100644 index 000000000..49357b388 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the MX record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The list of MX records in the record set.') +param mxRecords array = [] + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource MX 'Microsoft.Network/privateDnsZones/MX@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + mxRecords: mxRecords + ttl: ttl + } +} + +@description('The name of the deployed MX record') +output name string = MX.name + +@description('The resource ID of the deployed MX record') +output resourceId string = MX.id + +@description('The resource group of the deployed MX record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/readme.md new file mode 100644 index 000000000..76d901b92 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/readme.md @@ -0,0 +1,58 @@ +# Private DNS Zone MX record `[Microsoft.Network/privateDnsZones/MX]` + +This module deploys a Private DNS Zone MX record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/MX` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the MX record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `mxRecords` | array | `[]` | The list of MX records in the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `mxRecords` + +```json +"mxRecords": { + "value": [ + { + "exchange": "string", + "preference": "int" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed MX record | +| `resourceGroupName` | string | The resource group of the deployed MX record | +| `resourceId` | string | The resource ID of the deployed MX record | + +## Template references + +- [Privatednszones/MX](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/MX) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/MX/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/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/deploy.bicep new file mode 100644 index 000000000..e7b066524 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the PTR record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The list of PTR records in the record set.') +param ptrRecords array = [] + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource PTR 'Microsoft.Network/privateDnsZones/PTR@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + ptrRecords: ptrRecords + ttl: ttl + } +} + +@description('The name of the deployed PTR record') +output name string = PTR.name + +@description('The resource ID of the deployed PTR record') +output resourceId string = PTR.id + +@description('The resource group of the deployed PTR record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/readme.md new file mode 100644 index 000000000..f57d6db67 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone PTR record `[Microsoft.Network/privateDnsZones/PTR]` + +This module deploys a Private DNS Zone PTR record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/PTR` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the PTR record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ptrRecords` | array | `[]` | The list of PTR records in the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `ptrRecords` + +```json +"ptrRecords": { + "value": [ + { + "ptrdname": "string" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed PTR record | +| `resourceGroupName` | string | The resource group of the deployed PTR record | +| `resourceId` | string | The resource ID of the deployed PTR record | + +## Template references + +- [Privatednszones/PTR](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/PTR) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/PTR/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/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/deploy.bicep new file mode 100644 index 000000000..45079fc46 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the SOA record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. A SOA record.') +param soaRecord object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource SOA 'Microsoft.Network/privateDnsZones/SOA@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + soaRecord: soaRecord + ttl: ttl + } +} + +@description('The name of the deployed SOA record') +output name string = SOA.name + +@description('The resource ID of the deployed SOA record') +output resourceId string = SOA.id + +@description('The resource group of the deployed SOA record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/readme.md new file mode 100644 index 000000000..14dfbc674 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/readme.md @@ -0,0 +1,61 @@ +# Private DNS Zone SOA record `[Microsoft.Network/privateDnsZones/SOA]` + +This module deploys a Private DNS Zone SOA record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/SOA` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SOA record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `soaRecord` | object | `{object}` | A SOA record. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `soaRecord` + +```json +"soaRecord": { + "value": { + "email": "string", + "expireTime": "int", + "host": "string", + "minimumTtl": "int", + "refreshTime": "int", + "retryTime": "int", + "serialNumber": "int" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed SOA record | +| `resourceGroupName` | string | The resource group of the deployed SOA record | +| `resourceId` | string | The resource ID of the deployed SOA record | + +## Template references + +- [Privatednszones/SOA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SOA) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/SOA/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/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/deploy.bicep new file mode 100644 index 000000000..ace6ab941 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the SRV record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The list of SRV records in the record set.') +param srvRecords array = [] + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource SRV 'Microsoft.Network/privateDnsZones/SRV@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + srvRecords: srvRecords + ttl: ttl + } +} + +@description('The name of the deployed SRV record') +output name string = SRV.name + +@description('The resource ID of the deployed SRV record') +output resourceId string = SRV.id + +@description('The resource group of the deployed SRV record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/readme.md new file mode 100644 index 000000000..d1dd271a0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/readme.md @@ -0,0 +1,60 @@ +# Private DNS Zone SRV record `[Microsoft.Network/privateDnsZones/SRV]` + +This module deploys a Private DNS Zone TXT record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/SRV` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the SRV record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `srvRecords` | array | `[]` | The list of SRV records in the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | + + +### Parameter Usage: `srvRecords` + +```json +"srvRecords": { + "value": [ + { + "port": "int", + "priority": "int", + "target": "string", + "weight": "int" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed SRV record | +| `resourceGroupName` | string | The resource group of the deployed SRV record | +| `resourceId` | string | The resource ID of the deployed SRV record | + +## Template references + +- [Privatednszones/SRV](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SRV) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/SRV/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/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/deploy.bicep new file mode 100644 index 000000000..23d7bf3da --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/deploy.bicep @@ -0,0 +1,52 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Required. The name of the TXT record.') +param name string + +@description('Optional. The metadata attached to the record set.') +param metadata object = {} + +@description('Optional. The TTL (time-to-live) of the records in the record set.') +param ttl int = 3600 + +@description('Optional. The list of TXT records in the record set.') +param txtRecords array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource TXT 'Microsoft.Network/privateDnsZones/TXT@2020-06-01' = { + name: name + parent: privateDnsZone + properties: { + metadata: metadata + ttl: ttl + txtRecords: txtRecords + } +} + +@description('The name of the deployed TXT record') +output name string = TXT.name + +@description('The resource ID of the deployed TXT record') +output resourceId string = TXT.id + +@description('The resource group of the deployed TXT record') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/readme.md new file mode 100644 index 000000000..71fab1d72 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/readme.md @@ -0,0 +1,57 @@ +# Private DNS Zone TXT record `[Microsoft.Network/privateDnsZones/TXT]` + +This module deploys a Private DNS Zone TXT record. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/TXT` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the TXT record. | +| `privateDnsZoneName` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `metadata` | object | `{object}` | The metadata attached to the record set. | +| `ttl` | int | `3600` | The TTL (time-to-live) of the records in the record set. | +| `txtRecords` | array | `[]` | The list of TXT records in the record set. | + + +### Parameter Usage: `txtRecords` + +```json +"txtRecords": { + "value": [ + { + "value": [ "string" ] + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed TXT record | +| `resourceGroupName` | string | The resource group of the deployed TXT record | +| `resourceId` | string | The resource ID of the deployed TXT record | + +## Template references + +- [Privatednszones/TXT](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/TXT) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/TXT/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/carml/1.2.0/Microsoft.Network/privateDnsZones/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/deploy.bicep new file mode 100644 index 000000000..4a3f257cb --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/deploy.bicep @@ -0,0 +1,205 @@ +@description('Required. Private DNS zone name.') +param name string + +@description('Optional. Array of A records.') +param a array = [] + +@description('Optional. Array of AAAA records.') +param aaaa array = [] + +@description('Optional. Array of CNAME records.') +param cname array = [] + +@description('Optional. Array of MX records.') +param mx array = [] + +@description('Optional. Array of PTR records.') +param ptr array = [] + +@description('Optional. Array of SOA records.') +param soa array = [] + +@description('Optional. Array of SRV records.') +param srv array = [] + +@description('Optional. Array of TXT records.') +param txt array = [] + +@description('Optional. Array of custom objects describing vNet links of the DNS zone. Each object should contain properties \'vnetResourceId\' and \'registrationEnabled\'. The \'vnetResourceId\' is a resource ID of a vNet to link, \'registrationEnabled\' (bool) enables automatic DNS registration in the zone for the linked vNet.') +param virtualNetworkLinks array = [] + +@description('Optional. The location of the PrivateDNSZone. Should be global.') +param location string = 'global' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: name + location: location + tags: tags +} + +module privateDnsZone_A 'A/deploy.bicep' = [for (aRecord, index) in a: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-ARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: aRecord.name + aRecords: contains(aRecord, 'aRecords') ? aRecord.aRecords : [] + metadata: contains(aRecord, 'metadata') ? aRecord.metadata : {} + ttl: contains(aRecord, 'ttl') ? aRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_AAAA 'AAAA/deploy.bicep' = [for (aaaaRecord, index) in aaaa: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-AAAARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: aaaaRecord.name + aaaaRecords: contains(aaaaRecord, 'aaaaRecords') ? aaaaRecord.aaaaRecords : [] + metadata: contains(aaaaRecord, 'metadata') ? aaaaRecord.metadata : {} + ttl: contains(aaaaRecord, 'ttl') ? aaaaRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_CNAME 'CNAME/deploy.bicep' = [for (cnameRecord, index) in cname: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-CNAMERecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: cnameRecord.name + cnameRecord: contains(cnameRecord, 'cnameRecord') ? cnameRecord.cnameRecord : {} + metadata: contains(cnameRecord, 'metadata') ? cnameRecord.metadata : {} + ttl: contains(cnameRecord, 'ttl') ? cnameRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_MX 'MX/deploy.bicep' = [for (mxRecord, index) in mx: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-MXRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: mxRecord.name + metadata: contains(mxRecord, 'metadata') ? mxRecord.metadata : {} + mxRecords: contains(mxRecord, 'mxRecords') ? mxRecord.mxRecords : [] + ttl: contains(mxRecord, 'ttl') ? mxRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_PTR 'PTR/deploy.bicep' = [for (ptrRecord, index) in ptr: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-PTRRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: ptrRecord.name + metadata: contains(ptrRecord, 'metadata') ? ptrRecord.metadata : {} + ptrRecords: contains(ptrRecord, 'ptrRecords') ? ptrRecord.ptrRecords : [] + ttl: contains(ptrRecord, 'ttl') ? ptrRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_SOA 'SOA/deploy.bicep' = [for (soaRecord, index) in soa: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SOARecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: soaRecord.name + metadata: contains(soaRecord, 'metadata') ? soaRecord.metadata : {} + soaRecord: contains(soaRecord, 'soaRecord') ? soaRecord.soaRecord : {} + ttl: contains(soaRecord, 'ttl') ? soaRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_SRV 'SRV/deploy.bicep' = [for (srvRecord, index) in srv: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-SRVRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: srvRecord.name + metadata: contains(srvRecord, 'metadata') ? srvRecord.metadata : {} + srvRecords: contains(srvRecord, 'srvRecords') ? srvRecord.srvRecords : [] + ttl: contains(srvRecord, 'ttl') ? srvRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_TXT 'TXT/deploy.bicep' = [for (txtRecord, index) in txt: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-TXTRecord-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: txtRecord.name + metadata: contains(txtRecord, 'metadata') ? txtRecord.metadata : {} + txtRecords: contains(txtRecord, 'txtRecords') ? txtRecord.txtRecords : [] + ttl: contains(txtRecord, 'ttl') ? txtRecord.ttl : 3600 + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module privateDnsZone_virtualNetworkLinks 'virtualNetworkLinks/deploy.bicep' = [for (virtualNetworkLink, index) in virtualNetworkLinks: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-VirtualNetworkLink-${index}' + params: { + privateDnsZoneName: privateDnsZone.name + name: contains(virtualNetworkLink, 'name') ? virtualNetworkLink.name : '${last(split(virtualNetworkLink.virtualNetworkResourceId, '/'))}-vnetlink' + virtualNetworkResourceId: virtualNetworkLink.virtualNetworkResourceId + location: contains(virtualNetworkLink, 'location') ? virtualNetworkLink.location : 'global' + registrationEnabled: contains(virtualNetworkLink, 'registrationEnabled') ? virtualNetworkLink.registrationEnabled : false + tags: contains(virtualNetworkLink, 'tags') ? virtualNetworkLink.tags : {} + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +resource privateDnsZone_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateDnsZone.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateDnsZone +} + +module privateDnsZone_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PrivateDnsZone-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateDnsZone.id + } +}] + +@description('The resource group the private DNS zone was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the private DNS zone') +output name string = privateDnsZone.name + +@description('The resource ID of the private DNS zone') +output resourceId string = privateDnsZone.id diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/readme.md new file mode 100644 index 000000000..bfa77e582 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/readme.md @@ -0,0 +1,119 @@ +# Private DNS Zones `[Microsoft.Network/privateDnsZones]` + +This template deploys a private DNS zone. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateDnsZones` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/A` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/AAAA` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/CNAME` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/MX` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/PTR` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/SOA` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/SRV` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/TXT` | 2020-06-01 | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Private DNS zone name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `a` | _[a](a/readme.md)_ array | `[]` | | Array of A records. | +| `aaaa` | _[aaaa](aaaa/readme.md)_ array | `[]` | | Array of AAAA records. | +| `cname` | _[cname](cname/readme.md)_ array | `[]` | | Array of CNAME records. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `'global'` | | The location of the PrivateDNSZone. Should be global. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `mx` | _[mx](mx/readme.md)_ array | `[]` | | Array of MX records. | +| `ptr` | _[ptr](ptr/readme.md)_ array | `[]` | | Array of PTR records. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `soa` | _[soa](soa/readme.md)_ array | `[]` | | Array of SOA records. | +| `srv` | _[srv](srv/readme.md)_ array | `[]` | | Array of SRV records. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `txt` | _[txt](txt/readme.md)_ array | `[]` | | Array of TXT records. | +| `virtualNetworkLinks` | _[virtualNetworkLinks](virtualNetworkLinks/readme.md)_ array | `[]` | | Array of custom objects describing vNet links of the DNS zone. Each object should contain properties 'vnetResourceId' and 'registrationEnabled'. The 'vnetResourceId' is a resource ID of a vNet to link, 'registrationEnabled' (bool) enables automatic DNS registration in the zone for the linked vNet. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private DNS zone | +| `resourceGroupName` | string | The resource group the private DNS zone was deployed into | +| `resourceId` | string | The resource ID of the private DNS zone | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privatednszones](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones) +- [Privatednszones/A](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/A) +- [Privatednszones/AAAA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/AAAA) +- [Privatednszones/CNAME](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/CNAME) +- [Privatednszones/MX](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/MX) +- [Privatednszones/PTR](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/PTR) +- [Privatednszones/SOA](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SOA) +- [Privatednszones/SRV](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/SRV) +- [Privatednszones/TXT](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/TXT) +- [Privatednszones/Virtualnetworklinks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/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/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep new file mode 100644 index 000000000..4785655fa --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/deploy.bicep @@ -0,0 +1,58 @@ +@description('Required. Private DNS zone name.') +param privateDnsZoneName string + +@description('Optional. The name of the virtual network link.') +param name string = '${last(split(virtualNetworkResourceId, '/'))}-vnetlink' + +@description('Optional. The location of the PrivateDNSZone. Should be global.') +param location string = 'global' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled?') +param registrationEnabled bool = false + +@description('Required. Link to another virtual network resource ID.') +param virtualNetworkResourceId string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = { + name: privateDnsZoneName +} + +resource virtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { + name: name + parent: privateDnsZone + location: location + tags: tags + properties: { + registrationEnabled: registrationEnabled + virtualNetwork: { + id: virtualNetworkResourceId + } + } +} + +@description('The name of the deployed virtual network link') +output name string = virtualNetworkLink.name + +@description('The resource ID of the deployed virtual network link') +output resourceId string = virtualNetworkLink.id + +@description('The resource group of the deployed virtual network link') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md b/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md new file mode 100644 index 000000000..1799010e4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/readme.md @@ -0,0 +1,63 @@ +# Private DNS Zone Virtual Network Link `[Microsoft.Network/privateDnsZones/virtualNetworkLinks]` + +This module deploys private dns zone virtual network links. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateDnsZones/virtualNetworkLinks` | 2020-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateDnsZoneName` | string | Private DNS zone name. | +| `virtualNetworkResourceId` | string | Link to another virtual network resource ID. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `'global'` | The location of the PrivateDNSZone. Should be global. | +| `name` | string | `[format('{0}-vnetlink', last(split(parameters('virtualNetworkResourceId'), '/')))]` | The name of the virtual network link. | +| `registrationEnabled` | bool | `False` | Is auto-registration of virtual machine records in the virtual network in the Private DNS zone enabled? | +| `tags` | object | `{object}` | Tags of the resource. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed virtual network link | +| `resourceGroupName` | string | The resource group of the deployed virtual network link | +| `resourceId` | string | The resource ID of the deployed virtual network link | + +## Template references + +- [Privatednszones/Virtualnetworklinks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2020-06-01/privateDnsZones/virtualNetworkLinks) diff --git a/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/version.json b/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateDnsZones/virtualNetworkLinks/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/carml/1.2.0/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep b/carml/1.2.0/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/.bicep/nested_pid.bicep @@ -0,0 +1 @@ + diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e92085961 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(privateEndpoint.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: privateEndpoint +}] diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json new file mode 100644 index 000000000..bfe13c34e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/.parameters/min.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pe-kvlt-min-001" + }, + "targetSubnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + }, + "serviceResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-pe" + }, + "groupId": { + "value": [ + "vault" + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/privateEndpoints/.parameters/parameters.json new file mode 100644 index 000000000..5b5f6f17b --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/.parameters/parameters.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pe-kvlt-001" + }, + "targetSubnetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + }, + "serviceResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-pe" + }, + "groupId": { + "value": [ + "vault" + ] + }, + "privateDnsZoneGroups": { + "value": [ + { + "privateDNSResourceIds": [ + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.vaultcore.azure.net" + ] + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateEndpoints/deploy.bicep new file mode 100644 index 000000000..a84d6bfd5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/deploy.bicep @@ -0,0 +1,106 @@ +@description('Required. Name of the private endpoint resource to create.') +param name string + +@description('Required. Resource ID of the subnet where the endpoint needs to be created.') +param targetSubnetResourceId string + +@description('Required. Resource ID of the resource that needs to be connected to the network.') +param serviceResourceId string + +@description('Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to.') +param groupId array + +@description('Optional. Array of Private DNS zone groups configuration on the private endpoint.') +param privateDnsZoneGroups array = [] + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags to be applied on all resources/resource groups in this deployment.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: serviceResourceId + groupIds: groupId + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: targetSubnetResourceId + } + customDnsConfigs: [] + } +} + +module privateEndpoint_privateDnsZoneGroups 'privateDnsZoneGroups/deploy.bicep' = [for (privateDnsZoneGroup, index) in privateDnsZoneGroups: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-PrivateDnsZoneGroup-${index}' + params: { + privateDNSResourceIds: privateDnsZoneGroup.privateDNSResourceIds + privateEndpointName: privateEndpoint.name + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +resource privateEndpoint_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${privateEndpoint.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateEndpoint +} + +module privateEndpoint_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PrivateEndpoint-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: privateEndpoint.id + } +}] + +@description('The resource group the private endpoint was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the private endpoint') +output resourceId string = privateEndpoint.id + +@description('The name of the private endpoint') +output name string = privateEndpoint.name diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep b/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep new file mode 100644 index 000000000..04ea26d87 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/deploy.bicep @@ -0,0 +1,51 @@ +@description('Required. The name of the private endpoint') +param privateEndpointName string + +@description('Required. List of private DNS resource IDs') +param privateDNSResourceIds array + +@description('Optional. The name of the private DNS Zone Group') +param name string = 'default' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +var privateDnsZoneConfigs = [for privateDNSResourceId in privateDNSResourceIds: { + name: privateEndpointName + properties: { + privateDnsZoneId: privateDNSResourceId + } +}] + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' existing = { + name: privateEndpointName +} + +resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-05-01' = { + name: name + parent: privateEndpoint + properties: { + privateDnsZoneConfigs: privateDnsZoneConfigs + } +} + +@description('The name of the private endpoint DNS zone group') +output name string = privateDnsZoneGroup.name + +@description('The resource ID of the private endpoint DNS zone group') +output resourceId string = privateDnsZoneGroup.id + +@description('The resource group the private endpoint DNS zone group was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md b/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md new file mode 100644 index 000000000..ae4c4219f --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/readme.md @@ -0,0 +1,43 @@ +# Network Private Endpoint Private DNS Zone Group `[Microsoft.Network/privateEndpoints/privateDnsZoneGroups]` + +This module deploys a private endpoint private DNS zone group + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateDNSResourceIds` | array | List of private DNS resource IDs | +| `privateEndpointName` | string | The name of the private endpoint | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the private DNS Zone Group | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private endpoint DNS zone group | +| `resourceGroupName` | string | The resource group the private endpoint DNS zone group was deployed into | +| `resourceId` | string | The resource ID of the private endpoint DNS zone group | + +## Template references + +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/version.json b/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/privateDnsZoneGroups/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/carml/1.2.0/Microsoft.Network/privateEndpoints/readme.md b/carml/1.2.0/Microsoft.Network/privateEndpoints/readme.md new file mode 100644 index 000000000..224aecd62 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/readme.md @@ -0,0 +1,108 @@ +# Private Endpoints `[Microsoft.Network/privateEndpoints]` + +This template deploys a private endpoint for a generic service. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-05-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource: + +- `PrivateDNSZone` +- `VirtualNetwork/subnet` +- The service that needs to be connected through private endpoint + +**Important**: Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `groupId` | array | Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to. | +| `name` | string | Name of the private endpoint resource to create. | +| `serviceResourceId` | string | Resource ID of the resource that needs to be connected to the network. | +| `targetSubnetResourceId` | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `privateDnsZoneGroups` | _[privateDnsZoneGroups](privateDnsZoneGroups/readme.md)_ array | `[]` | | Array of Private DNS zone groups configuration on the private endpoint. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags to be applied on all resources/resource groups in this deployment. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the private endpoint | +| `resourceGroupName` | string | The resource group the private endpoint was deployed into | +| `resourceId` | string | The resource ID of the private endpoint | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/privateEndpoints/version.json b/carml/1.2.0/Microsoft.Network/privateEndpoints/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/privateEndpoints/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/carml/1.2.0/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..e6e4397f3 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPAddresses/.bicep/nested_rbac.bicep @@ -0,0 +1,59 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpAddress.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpAddress +}] diff --git a/carml/1.2.0/Microsoft.Network/publicIPAddresses/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/publicIPAddresses/.parameters/parameters.json new file mode 100644 index 000000000..1e12e533b --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPAddresses/.parameters/parameters.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pip-x-001" + }, + "skuName": { + "value": "Standard" + }, + "publicIPAllocationMethod": { + "value": "Static" + }, + "zones": { + "value": [ + "1", + "2", + "3" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/publicIPAddresses/deploy.bicep b/carml/1.2.0/Microsoft.Network/publicIPAddresses/deploy.bicep new file mode 100644 index 000000000..cb6f57cfa --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPAddresses/deploy.bicep @@ -0,0 +1,194 @@ +@description('Required. The name of the Public IP Address') +param name string + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. The public IP address allocation method.') +@allowed([ + 'Dynamic' + 'Static' +]) +param publicIPAllocationMethod string = 'Dynamic' + +@description('Optional. Name of a public IP address SKU.') +@allowed([ + 'Basic' + 'Standard' +]) +param skuName string = 'Basic' + +@description('Optional. Tier of a public IP address SKU.') +@allowed([ + 'Global' + 'Regional' +]) +param skuTier string = 'Regional' + +@description('Optional. A list of availability zones denoting the IP allocated for the resource needs to come from.') +param zones array = [] + +@description('Optional. IP address version.') +@allowed([ + 'IPv4' + 'IPv6' +]) +param publicIPAddressVersion string = 'IPv4' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param diagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIPPrefix = { + id: publicIPPrefixResourceId +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource publicIpAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: skuTier + } + zones: zones + properties: { + publicIPAddressVersion: publicIPAddressVersion + publicIPAllocationMethod: publicIPAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? publicIPPrefix : null + idleTimeoutInMinutes: 4 + ipTags: [] + } +} + +resource publicIpAddress_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpAddress.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpAddress +} + +resource publicIpAddress_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: publicIpAddress +} + +module publicIpAddress_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PIPAddress-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpAddress.id + } +}] + +@description('The resource group the public IP address was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP address') +output name string = publicIpAddress.name + +@description('The resource ID of the public IP address') +output resourceId string = publicIpAddress.id + +@description('The public IP address of the of the public IP address resource') +output ipAddress string = publicIpAddress.properties.ipAddress diff --git a/carml/1.2.0/Microsoft.Network/publicIPAddresses/readme.md b/carml/1.2.0/Microsoft.Network/publicIPAddresses/readme.md new file mode 100644 index 000000000..62ee6c684 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPAddresses/readme.md @@ -0,0 +1,107 @@ +# Public IP Addresses `[Microsoft.Network/publicIPAddresses]` + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Public IP Address | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicIPAddressVersion` | string | `'IPv4'` | `[IPv4, IPv6]` | IP address version. | +| `publicIPAllocationMethod` | string | `'Dynamic'` | `[Dynamic, Static]` | The public IP address allocation method. | +| `publicIPPrefixResourceId` | string | `''` | | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `skuName` | string | `'Basic'` | `[Basic, Standard]` | Name of a public IP address SKU. | +| `skuTier` | string | `'Regional'` | `[Global, Regional]` | Tier of a public IP address SKU. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `zones` | array | `[]` | | A list of availability zones denoting the IP allocated for the resource needs to come from. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `ipAddress` | string | The public IP address of the of the public IP address resource | +| `name` | string | The name of the public IP address | +| `resourceGroupName` | string | The resource group the public IP address was deployed into | +| `resourceId` | string | The resource ID of the public IP address | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/publicIPAddresses/version.json b/carml/1.2.0/Microsoft.Network/publicIPAddresses/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPAddresses/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/carml/1.2.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..fddcae250 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(publicIpPrefix.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: publicIpPrefix +}] diff --git a/carml/1.2.0/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json new file mode 100644 index 000000000..5b4074820 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/.parameters/parameters.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-pippfx-x-001" + }, + "prefixLength": { + "value": 28 + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/publicIPPrefixes/deploy.bicep b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/deploy.bicep new file mode 100644 index 000000000..82f8b7b8a --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/deploy.bicep @@ -0,0 +1,82 @@ +@description('Required. Name of the Public IP Prefix') +@minLength(1) +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. Length of the Public IP Prefix') +@minValue(28) +@maxValue(31) +param prefixLength int + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource publicIpPrefix 'Microsoft.Network/publicIPPrefixes@2021-05-01' = { + name: name + location: location + tags: tags + sku: { + name: 'Standard' + } + properties: { + publicIPAddressVersion: 'IPv4' + prefixLength: prefixLength + } +} + +resource publicIpPrefix_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${publicIpPrefix.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: publicIpPrefix +} + +module publicIpPrefix_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-PIPPrefix-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: publicIpPrefix.id + } +}] + +@description('The resource ID of the public IP prefix') +output resourceId string = publicIpPrefix.id + +@description('The resource group the public IP prefix was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the public IP prefix') +output name string = publicIpPrefix.name diff --git a/carml/1.2.0/Microsoft.Network/publicIPPrefixes/readme.md b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/readme.md new file mode 100644 index 000000000..e1b27aa1d --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/readme.md @@ -0,0 +1,93 @@ +# Public IP Prefixes `[Microsoft.Network/publicIPPrefixes]` + +This template deploys a public IP prefix. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/publicIPPrefixes` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Public IP Prefix | +| `prefixLength` | int | Length of the Public IP Prefix | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the public IP prefix | +| `resourceGroupName` | string | The resource group the public IP prefix was deployed into | +| `resourceId` | string | The resource ID of the public IP prefix | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipprefixes](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPPrefixes) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Network/publicIPPrefixes/version.json b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/publicIPPrefixes/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/carml/1.2.0/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..105d1a0ba --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/routeTables/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource routeTable 'Microsoft.Network/routeTables@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(routeTable.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: routeTable +}] diff --git a/carml/1.2.0/Microsoft.Network/routeTables/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/routeTables/.parameters/parameters.json new file mode 100644 index 000000000..edd5dba92 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/routeTables/.parameters/parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-udr-x-001" + }, + "routes": { + "value": [ + { + "name": "default", + "properties": { + "addressPrefix": "0.0.0.0/0", + "nextHopType": "VirtualAppliance", + "nextHopIpAddress": "172.16.0.20" + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/routeTables/deploy.bicep b/carml/1.2.0/Microsoft.Network/routeTables/deploy.bicep new file mode 100644 index 000000000..774aa9571 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/routeTables/deploy.bicep @@ -0,0 +1,79 @@ +@description('Required. Name given for the hub route table.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. An Array of Routes to be established within the hub route table.') +param routes array = [] + +@description('Optional. Switch to disable BGP route propagation.') +param disableBgpRoutePropagation bool = false + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource routeTable 'Microsoft.Network/routeTables@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + routes: routes + disableBgpRoutePropagation: disableBgpRoutePropagation + } +} + +resource routeTable_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${routeTable.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: routeTable +} + +module routeTable_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RouteTable-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: routeTable.id + } +}] + +@description('The resource group the route table was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the route table') +output name string = routeTable.name + +@description('The resource ID of the route table') +output resourceId string = routeTable.id diff --git a/carml/1.2.0/Microsoft.Network/routeTables/readme.md b/carml/1.2.0/Microsoft.Network/routeTables/readme.md new file mode 100644 index 000000000..cf448745c --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/routeTables/readme.md @@ -0,0 +1,136 @@ +# Route Tables `[Microsoft.Network/routeTables]` + +This module deploys a user defined route table. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/routeTables` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name given for the hub route table. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `disableBgpRoutePropagation` | bool | `False` | | Switch to disable BGP route propagation. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `routes` | array | `[]` | | An Array of Routes to be established within the hub route table. | +| `tags` | object | `{object}` | | Tags of the resource. | + + +### Parameter Usage: `routes` + +The `routes` parameter accepts a JSON Array of Route objects to deploy to the Route Table. + +Here's an example of specifying a few routes: + +```json +"routes": { + "value": [ + { + "name": "tojumpboxes", + "properties": { + "addressPrefix": "172.16.0.48/28", + "nextHopType": "VnetLocal" + } + }, + { + "name": "tosharedservices", + "properties": { + "addressPrefix": "172.16.0.64/27", + "nextHopType": "VnetLocal" + } + }, + { + "name": "toonprem", + "properties": { + "addressPrefix": "10.0.0.0/8", + "nextHopType": "VirtualNetworkGateway" + } + }, + { + "name": "tonva", + "properties": { + "addressPrefix": "172.16.0.0/18", + "nextHopType": "VirtualAppliance", + "nextHopIpAddress": "172.16.0.20" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the route table | +| `resourceGroupName` | string | The resource group the route table was deployed into | +| `resourceId` | string | The resource ID of the route table | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Routetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/routeTables) diff --git a/carml/1.2.0/Microsoft.Network/routeTables/version.json b/carml/1.2.0/Microsoft.Network/routeTables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/routeTables/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/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..6056c70be --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/.bicep/nested_rbac.bicep @@ -0,0 +1,56 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource trafficmanagerprofile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(trafficmanagerprofile.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: trafficmanagerprofile +}] diff --git a/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json new file mode 100644 index 000000000..fd3469ed6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/.parameters/parameters.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "tm-000001" + }, + "relativeName": { + "value": "tm-000001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/deploy.bicep b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/deploy.bicep new file mode 100644 index 000000000..10eb3a517 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/deploy.bicep @@ -0,0 +1,191 @@ +@description('Required. Name of the Traffic Manager') +@minLength(1) +param name string + +@description('Optional. The status of the Traffic Manager profile.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param profileStatus string = 'Enabled' + +@description('Optional. The traffic routing method of the Traffic Manager profile.') +@allowed([ + 'Performance' + 'Priority' + 'Weighted' + 'Geographic' + 'MultiValue' + 'Subnet' +]) +param trafficRoutingMethod string = 'Performance' + +@description('Required. The relative DNS name provided by this Traffic Manager profile. This value is combined with the DNS domain name used by Azure Traffic Manager to form the fully-qualified domain name (FQDN) of the profile.') +param relativeName string + +@description('Optional. The DNS Time-To-Live (TTL), in seconds. This informs the local DNS resolvers and DNS clients how long to cache DNS responses provided by this Traffic Manager profile.') +param ttl int = 60 + +@description('Optional. The endpoint monitoring settings of the Traffic Manager profile.') +param monitorConfig object = { + protocol: 'http' + port: '80' + path: '/' +} + +@description('Optional. The list of endpoints in the Traffic Manager profile.') +param endpoints array = [] + +@description('Optional. Indicates whether Traffic View is \'Enabled\' or \'Disabled\' for the Traffic Manager profile. Null, indicates \'Disabled\'. Enabling this feature will increase the cost of the Traffic Manage profile.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param trafficViewEnrollmentStatus string = 'Disabled' + +@description('Optional. Maximum number of endpoints to be returned for MultiValue routing type.') +param maxReturn int = 1 + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Resource tags.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'ProbeHealthStatusEvents' +]) +param diagnosticLogCategoriesToEnable array = [ + 'ProbeHealthStatusEvents' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2018-08-01' = { + name: name + tags: tags + location: 'global' + properties: { + profileStatus: profileStatus + trafficRoutingMethod: trafficRoutingMethod + dnsConfig: { + relativeName: relativeName + ttl: ttl + } + monitorConfig: monitorConfig + endpoints: endpoints + trafficViewEnrollmentStatus: trafficViewEnrollmentStatus + maxReturn: maxReturn + } +} + +resource trafficManagerProfile_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${trafficManagerProfile.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: trafficManagerProfile +} + +resource trafficManagerProfile_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: trafficManagerProfile +} + +module trafficManagerProfile_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name)}-TrafficManagerProfile-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: trafficManagerProfile.id + } +}] + +@description('The resource ID of the traffix manager') +output resourceId string = trafficManagerProfile.id + +@description('The resource group the traffix manager was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the traffix manager was deployed into') +output name string = trafficManagerProfile.name diff --git a/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/readme.md b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/readme.md new file mode 100644 index 000000000..bc48174e2 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/readme.md @@ -0,0 +1,147 @@ +# Traffic Manager Profiles `[Microsoft.Network/trafficmanagerprofiles]` + +This module deploys a traffic manager profile. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/trafficmanagerprofiles` | 2018-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Traffic Manager | +| `relativeName` | string | The relative DNS name provided by this Traffic Manager profile. This value is combined with the DNS domain name used by Azure Traffic Manager to form the fully-qualified domain name (FQDN) of the profile. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[ProbeHealthStatusEvents]` | `[ProbeHealthStatusEvents]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `endpoints` | array | `[]` | | The list of endpoints in the Traffic Manager profile. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxReturn` | int | `1` | | Maximum number of endpoints to be returned for MultiValue routing type. | +| `monitorConfig` | object | `{object}` | | The endpoint monitoring settings of the Traffic Manager profile. | +| `profileStatus` | string | `'Enabled'` | `[Enabled, Disabled]` | The status of the Traffic Manager profile. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Resource tags. | +| `trafficRoutingMethod` | string | `'Performance'` | `[Performance, Priority, Weighted, Geographic, MultiValue, Subnet]` | The traffic routing method of the Traffic Manager profile. | +| `trafficViewEnrollmentStatus` | string | `'Disabled'` | `[Disabled, Enabled]` | Indicates whether Traffic View is 'Enabled' or 'Disabled' for the Traffic Manager profile. Null, indicates 'Disabled'. Enabling this feature will increase the cost of the Traffic Manage profile. | +| `ttl` | int | `60` | | The DNS Time-To-Live (TTL), in seconds. This informs the local DNS resolvers and DNS clients how long to cache DNS responses provided by this Traffic Manager profile. | + + +### Parameter Usage: `monitorConfig` + +```json +"monitorConfig": { + "value": + { + "protocol": "http", + "port": "80", + "path": "/" + } +} +``` + +### Parameter Usage: `endpoints` + +```json +"endpoints": { + "value": + [ + { + "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/trafficManagerProfiles//azureEndpoints/", + "name": "MyEndpoint001", + "type": "Microsoft.Network/trafficManagerProfiles/azureEndpoints", + "properties": + { + "endpointStatus": "Enabled", + "endpointMonitorStatus": "CheckingEndpoint", + "targetResourceId": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups//providers/Microsoft.Network/publicIPAddresses/", + "target": "my-pip-001.eastus.cloudapp.azure.com", + "weight": 1, + "priority": 1, + "endpointLocation": "East US" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the traffix manager was deployed into | +| `resourceGroupName` | string | The resource group the traffix manager was deployed into | +| `resourceId` | string | The resource ID of the traffix manager | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Trafficmanagerprofiles](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2018-08-01/trafficmanagerprofiles) diff --git a/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/version.json b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/trafficmanagerprofiles/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/carml/1.2.0/Microsoft.Network/virtualHubs/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/virtualHubs/.parameters/min.parameters.json new file mode 100644 index 000000000..dbe2fa650 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/.parameters/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": { + "name": { + "value": "<>-az-vhub-min-001" + }, + "addressPrefix": { + "value": "10.0.0.0/16" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/adp-<>-az-vw-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/virtualHubs/.parameters/parameters.json new file mode 100644 index 000000000..ed856582a --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/.parameters/parameters.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vhub-x-001" + }, + "addressPrefix": { + "value": "10.1.0.0/16" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/adp-<>-az-vw-x-001" + }, + "hubRouteTables": { + "value": [ + { + "name": "routeTable1" + } + ] + }, + "hubVirtualNetworkConnections": { + "value": [ + { + "name": "connection1", + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-vhub", + "routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vHub-x-001/hubRouteTables/routeTable1" + }, + "propagatedRouteTables": { + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vHub-x-001/hubRouteTables/routeTable1" + } + ], + "labels": [ + "none" + ] + } + } + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualHubs/deploy.bicep new file mode 100644 index 000000000..cbd6ae311 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/deploy.bicep @@ -0,0 +1,173 @@ +@description('Required. The virtual hub name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Required. Address-prefix for this VirtualHub.') +param addressPrefix string + +@description('Optional. Flag to control transit for VirtualRouter hub.') +param allowBranchToBranchTraffic bool = true + +@description('Optional. Resource ID of the Azure Firewall to link to') +param azureFirewallId string = '' + +@description('Optional. Resource ID of the Express Route Gateway to link to') +param expressRouteGatewayId string = '' + +@description('Optional. Resource ID of the Point-to-Site VPN Gateway to link to') +param p2SVpnGatewayId string = '' + +@description('Optional. The preferred routing gateway types') +@allowed([ + 'ExpressRoute' + 'None' + 'VpnGateway' + '' +]) +param preferredRoutingGateway string = '' + +@description('Optional. VirtualHub route tables') +param routeTableRoutes array = [] + +@description('Optional. ID of the Security Partner Provider to link to') +param securityPartnerProviderId string = '' + +@description('Optional. The Security Provider name.') +param securityProviderName string = '' + +@allowed([ + 'Basic' + 'Standard' +]) +@description('Optional. The sku of this VirtualHub.') +param sku string = 'Standard' + +@description('Optional. List of all virtual hub route table v2s associated with this VirtualHub.') +param virtualHubRouteTableV2s array = [] + +@description('Optional. VirtualRouter ASN.') +param virtualRouterAsn int = -1 + +@description('Optional. VirtualRouter IPs.') +param virtualRouterIps array = [] + +@description('Required. Resource ID of the virtual WAN to link to') +param virtualWanId string + +@description('Optional. Resource ID of the VPN Gateway to link to') +param vpnGatewayId string = '' + +@description('Optional. Route tables to create for the virtual hub.') +param hubRouteTables array = [] + +@description('Optional. Virtual network connections to create for the virtual hub.') +param hubVirtualNetworkConnections array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressPrefix: addressPrefix + allowBranchToBranchTraffic: allowBranchToBranchTraffic + azureFirewall: !empty(azureFirewallId) ? { + id: azureFirewallId + } : null + expressRouteGateway: !empty(expressRouteGatewayId) ? { + id: expressRouteGatewayId + } : null + p2SVpnGateway: !empty(p2SVpnGatewayId) ? { + id: p2SVpnGatewayId + } : null + preferredRoutingGateway: !empty(preferredRoutingGateway) ? any(preferredRoutingGateway) : null + routeTable: !empty(routeTableRoutes) ? { + routes: routeTableRoutes + } : null + securityPartnerProvider: !empty(securityPartnerProviderId) ? { + id: securityPartnerProviderId + } : null + securityProviderName: securityProviderName + sku: sku + virtualHubRouteTableV2s: virtualHubRouteTableV2s + virtualRouterAsn: virtualRouterAsn != -1 ? virtualRouterAsn : null + virtualRouterIps: !empty(virtualRouterIps) ? virtualRouterIps : null + virtualWan: { + id: virtualWanId + } + vpnGateway: !empty(vpnGatewayId) ? { + id: vpnGatewayId + } : null + } +} + +resource virtualHub_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualHub.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualHub +} + +module virtualHub_routeTables 'hubRouteTables/deploy.bicep' = [for (routeTable, index) in hubRouteTables: { + name: '${uniqueString(deployment().name, location)}-routeTable-${index}' + params: { + virtualHubName: virtualHub.name + name: routeTable.name + labels: contains(routeTable, 'labels') ? routeTable.labels : [] + routes: contains(routeTable, 'routes') ? routeTable.routes : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module virtualHub_hubVirtualNetworkConnections 'hubVirtualNetworkConnections/deploy.bicep' = [for (virtualNetworkConnection, index) in hubVirtualNetworkConnections: { + name: '${uniqueString(deployment().name, location)}-connection-${index}' + params: { + virtualHubName: virtualHub.name + name: virtualNetworkConnection.name + enableInternetSecurity: contains(virtualNetworkConnection, 'enableInternetSecurity') ? virtualNetworkConnection.enableInternetSecurity : true + remoteVirtualNetworkId: virtualNetworkConnection.remoteVirtualNetworkId + routingConfiguration: contains(virtualNetworkConnection, 'routingConfiguration') ? virtualNetworkConnection.routingConfiguration : {} + enableDefaultTelemetry: enableDefaultTelemetry + } + dependsOn: [ + virtualHub_routeTables + ] +}] + +@description('The resource group the virtual hub was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual hub') +output resourceId string = virtualHub.id + +@description('The name of the virtual hub') +output name string = virtualHub.name diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep new file mode 100644 index 000000000..221a76f44 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/deploy.bicep @@ -0,0 +1,48 @@ +@description('Required. The route table name.') +param name string + +@description('Required. The virtual hub name.') +param virtualHubName string + +@description('Optional. List of labels associated with this route table.') +param labels array = [] + +@description('Optional. List of all routes.') +param routes array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' existing = { + name: virtualHubName +} + +resource hubRouteTable 'Microsoft.Network/virtualHubs/hubRouteTables@2021-05-01' = { + name: name + parent: virtualHub + properties: { + labels: !empty(labels) ? labels : null + routes: !empty(routes) ? routes : null + } +} + +@description('The name of the deployed virtual hub route table') +output name string = hubRouteTable.name + +@description('The resource ID of the deployed virtual hub route table') +output resourceId string = hubRouteTable.id + +@description('The resource group the virtual hub route table was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/readme.md b/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/readme.md new file mode 100644 index 000000000..e34e97187 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/readme.md @@ -0,0 +1,44 @@ +# Virtual Hub Route Table `[Microsoft.Network/virtualHubs/hubRouteTables]` + +This module deploys virtual hub route tables. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs/hubRouteTables` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The route table name. | +| `virtualHubName` | string | The virtual hub name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `labels` | array | `[]` | List of labels associated with this route table. | +| `routes` | array | `[]` | List of all routes. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed virtual hub route table | +| `resourceGroupName` | string | The resource group the virtual hub route table was deployed into | +| `resourceId` | string | The resource ID of the deployed virtual hub route table | + +## Template references + +- [Virtualhubs/Hubroutetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubRouteTables) diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/version.json b/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/hubRouteTables/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/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep new file mode 100644 index 000000000..02d97d7e7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/deploy.bicep @@ -0,0 +1,54 @@ +@description('Required. The connection name.') +param name string + +@description('Required. The virtual hub name.') +param virtualHubName string + +@description('Optional. Enable internet security.') +param enableInternetSecurity bool = true + +@description('Required. Resource ID of the virtual network to link to') +param remoteVirtualNetworkId string + +@description('Optional. Routing Configuration indicating the associated and propagated route tables for this connection.') +param routingConfiguration object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2021-05-01' existing = { + name: virtualHubName +} + +resource hubVirtualNetworkConnection 'Microsoft.Network/virtualHubs/hubVirtualNetworkConnections@2021-05-01' = { + name: name + parent: virtualHub + properties: { + enableInternetSecurity: enableInternetSecurity + remoteVirtualNetwork: { + id: remoteVirtualNetworkId + } + routingConfiguration: !empty(routingConfiguration) ? routingConfiguration : null + } +} + +@description('The resource group the virtual hub connection was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual hub connection') +output resourceId string = hubVirtualNetworkConnection.id + +@description('The name of the virtual hub connection') +output name string = hubVirtualNetworkConnection.name diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md b/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md new file mode 100644 index 000000000..adc589d13 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/readme.md @@ -0,0 +1,49 @@ +# Virtual Hub Virtual Network Connections `[Microsoft.Network/virtualHubs/hubVirtualNetworkConnections]` + +This module deploys virtual hub virtual network connections. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The connection name. | +| `remoteVirtualNetworkId` | string | Resource ID of the virtual network to link to | +| `virtualHubName` | string | The virtual hub name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableInternetSecurity` | bool | `True` | Enable internet security. | +| `routingConfiguration` | object | `{object}` | Routing Configuration indicating the associated and propagated route tables for this connection. | + + +### Parameter Usage: `hubVirtualNetworkConnections` + +... + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual hub connection | +| `resourceGroupName` | string | The resource group the virtual hub connection was deployed into | +| `resourceId` | string | The resource ID of the virtual hub connection | + +## Template references + +- [Virtualhubs/Hubvirtualnetworkconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubVirtualNetworkConnections) diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/version.json b/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/hubVirtualNetworkConnections/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/carml/1.2.0/Microsoft.Network/virtualHubs/readme.md b/carml/1.2.0/Microsoft.Network/virtualHubs/readme.md new file mode 100644 index 000000000..96585d28e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/readme.md @@ -0,0 +1,84 @@ +# Virtual Hubs `[Microsoft.Network/virtualHubs]` + +This module deploys a Virtual Hub. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/virtualHubs` | 2021-05-01 | +| `Microsoft.Network/virtualHubs/hubRouteTables` | 2021-05-01 | +| `Microsoft.Network/virtualHubs/hubVirtualNetworkConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `addressPrefix` | string | Address-prefix for this VirtualHub. | +| `name` | string | The virtual hub name. | +| `virtualWanId` | string | Resource ID of the virtual WAN to link to | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBranchToBranchTraffic` | bool | `True` | | Flag to control transit for VirtualRouter hub. | +| `azureFirewallId` | string | `''` | | Resource ID of the Azure Firewall to link to | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `expressRouteGatewayId` | string | `''` | | Resource ID of the Express Route Gateway to link to | +| `hubRouteTables` | _[hubRouteTables](hubRouteTables/readme.md)_ array | `[]` | | Route tables to create for the virtual hub. | +| `hubVirtualNetworkConnections` | _[hubVirtualNetworkConnections](hubVirtualNetworkConnections/readme.md)_ array | `[]` | | Virtual network connections to create for the virtual hub. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `p2SVpnGatewayId` | string | `''` | | Resource ID of the Point-to-Site VPN Gateway to link to | +| `preferredRoutingGateway` | string | `''` | `[ExpressRoute, None, VpnGateway, ]` | The preferred routing gateway types | +| `routeTableRoutes` | array | `[]` | | VirtualHub route tables | +| `securityPartnerProviderId` | string | `''` | | ID of the Security Partner Provider to link to | +| `securityProviderName` | string | `''` | | The Security Provider name. | +| `sku` | string | `'Standard'` | `[Basic, Standard]` | The sku of this VirtualHub. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `virtualHubRouteTableV2s` | array | `[]` | | List of all virtual hub route table v2s associated with this VirtualHub. | +| `virtualRouterAsn` | int | `-1` | | VirtualRouter ASN. | +| `virtualRouterIps` | array | `[]` | | VirtualRouter IPs. | +| `vpnGatewayId` | string | `''` | | Resource ID of the VPN Gateway to link to | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual hub | +| `resourceGroupName` | string | The resource group the virtual hub was deployed into | +| `resourceId` | string | The resource ID of the virtual hub | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Virtualhubs](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs) +- [Virtualhubs/Hubroutetables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubRouteTables) +- [Virtualhubs/Hubvirtualnetworkconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualHubs/hubVirtualNetworkConnections) diff --git a/carml/1.2.0/Microsoft.Network/virtualHubs/version.json b/carml/1.2.0/Microsoft.Network/virtualHubs/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualHubs/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/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..5c5daeab2 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualNetworkGateway.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualNetworkGateway +}] diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json new file mode 100644 index 000000000..3de5a1f41 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.parameters/expressRoute.parameters.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-gw-er-001" + }, + "gatewayPipName": { + "value": "<>-az-gw-er-001-pip" + }, + "domainNameLabel": { + "value": [ + "<>-az-gw-er-dm-001" + ] + }, + "virtualNetworkGatewayType": { + "value": "ExpressRoute" + }, + "virtualNetworkGatewaySku": { + "value": "ErGw1AZ" + }, + "vNetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "tags": { + "value": { + "Environment": "Validation", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "", + "CostCenter": "", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.parameters.json b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.parameters.json new file mode 100644 index 000000000..8699d145e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/.parameters/vpn.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": "<>-az-gw-vpn-001" + }, + "domainNameLabel": { + "value": [ + "<>-az-gw-vpn-dm-001" + ] + }, + "virtualNetworkGatewayType": { + "value": "Vpn" + }, + "virtualNetworkGatewaySku": { + "value": "VpnGw1AZ" + }, + "publicIpZones": { + "value": [ + "1" + ] + }, + "vpnType": { + "value": "RouteBased" + }, + "activeActive": { + "value": true + }, + "vNetResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/deploy.bicep new file mode 100644 index 000000000..d99597c1b --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/deploy.bicep @@ -0,0 +1,408 @@ +@description('Required. Specifies the Virtual Network Gateway name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the name of the Public IP used by the Virtual Network Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the gateway\'s name.') +param gatewayPipName string = '${name}-pip1' + +@description('Optional. Specifies the name of the Public IP used by the Virtual Network Gateway when active-active configuration is required. If it\'s not provided, a \'-pip\' suffix will be appended to the gateway\'s name.') +param activeGatewayPipName string = '${name}-pip2' + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones.') +param publicIpZones array = [] + +@description('Optional. DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com') +param domainNameLabel array = [] + +@description('Required. Specifies the gateway type. E.g. VPN, ExpressRoute') +@allowed([ + 'Vpn' + 'ExpressRoute' +]) +param virtualNetworkGatewayType string + +@description('Required. The Sku of the Gateway.') +@allowed([ + 'Basic' + 'VpnGw1' + 'VpnGw2' + 'VpnGw3' + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'Standard' + 'HighPerformance' + 'UltraPerformance' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +]) +param virtualNetworkGatewaySku string + +@description('Required. Specifies the VPN type') +@allowed([ + 'PolicyBased' + 'RouteBased' +]) +param vpnType string = 'RouteBased' + +@description('Required. Virtual Network resource ID') +param vNetResourceId string + +@description('Optional. Value to specify if the Gateway should be deployed in active-active or active-passive configuration') +param activeActive bool = true + +@description('Optional. Value to specify if BGP is enabled or not') +param enableBgp bool = true + +@description('Optional. ASN value') +param asn int = 65815 + +@description('Optional. The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network.') +param vpnClientAddressPoolPrefix string = '' + +@description('Optional. Client root certificate data used to authenticate VPN clients.') +param clientRootCertData string = '' + +@description('Optional. Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet.') +param clientRevokedCertThumbprint string = '' + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param publicIpdiagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'GatewayDiagnosticLog' + 'TunnelDiagnosticLog' + 'RouteDiagnosticLog' + 'IKEDiagnosticLog' + 'P2SDiagnosticLog' +]) +param virtualNetworkGatewaydiagnosticLogCategoriesToEnable array = [ + 'GatewayDiagnosticLog' + 'TunnelDiagnosticLog' + 'RouteDiagnosticLog' + 'IKEDiagnosticLog' + 'P2SDiagnosticLog' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param virtualNetworkGatewayDiagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. The name of the diagnostic setting, if deployed.') +param publicIpDiagnosticSettingsName string = 'diagnosticSettings' + +// ================// +// Variables // +// ================// + +// Diagnostic Variables +var virtualNetworkGatewayDiagnosticsLogs = [for category in virtualNetworkGatewaydiagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var publicIpDiagnosticsLogs = [for category in publicIpdiagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +// Other Variables +var zoneRedundantSkus = [ + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'VpnGw4AZ' + 'VpnGw5AZ' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +] +var gatewayPipSku = contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? 'Standard' : 'Basic' +var gatewayPipAllocationMethod = contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? 'Static' : 'Dynamic' + +var isActiveActiveValid = virtualNetworkGatewayType != 'ExpressRoute' ? activeActive : false +var virtualGatewayPipName_var = isActiveActiveValid ? [ + gatewayPipName + activeGatewayPipName +] : [ + gatewayPipName +] + +var vpnType_var = virtualNetworkGatewayType != 'ExpressRoute' ? vpnType : 'PolicyBased' + +var isBgpValid = virtualNetworkGatewayType != 'ExpressRoute' ? enableBgp : false +var bgpSettings = { + asn: asn +} + +// Potential configurations (active-active vs active-passive) +var ipConfiguration = isActiveActiveValid ? [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig1' + } + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: isActiveActiveValid ? az.resourceId('Microsoft.Network/publicIPAddresses', activeGatewayPipName) : az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig2' + } +] : [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig1' + } +] + +var vpnClientConfiguration = { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] + } + vpnClientRootCertificates: !empty(clientRootCertData) ? [ + { + name: 'RootCert1' + properties: { + PublicCertData: clientRootCertData + } + } + ] : null + vpnClientRevokedCertificates: !empty(clientRevokedCertThumbprint) ? [ + { + name: 'RevokedCert1' + properties: { + Thumbprint: clientRevokedCertThumbprint + } + } + ] : null +} + +// ================// +// Deployments // +// ================// +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +// Public IPs +@batchSize(1) +resource virtualGatewayPublicIP 'Microsoft.Network/publicIPAddresses@2021-05-01' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: { + name: virtualGatewayPublicIpName + location: location + tags: tags + sku: { + name: gatewayPipSku + } + properties: { + publicIPAllocationMethod: gatewayPipAllocationMethod + publicIPPrefix: !empty(publicIPPrefixResourceId) ? { + id: publicIPPrefixResourceId + } : null + dnsSettings: length(virtualGatewayPipName_var) == length(domainNameLabel) ? { + domainNameLabel: domainNameLabel[index] + } : null + } + zones: contains(zoneRedundantSkus, virtualNetworkGatewaySku) ? publicIpZones : null +}] + +@batchSize(1) +resource virtualGatewayPublicIP_lock 'Microsoft.Authorization/locks@2017-04-01' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: if (lock != 'NotSpecified') { + name: '${virtualGatewayPublicIpName}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualGatewayPublicIP[index] +}] + +@batchSize(1) +resource virtualNetworkGatewayPublicIp_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipName_var: if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${virtualGatewayPublicIP[index].name}-${publicIpDiagnosticSettingsName}' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: publicIpDiagnosticsLogs + } + scope: virtualGatewayPublicIP[index] +}] + +// VNET Gateway +// ============ +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + ipConfigurations: ipConfiguration + activeActive: isActiveActiveValid + enableBgp: isBgpValid + bgpSettings: isBgpValid ? bgpSettings : null + sku: { + name: virtualNetworkGatewaySku + tier: virtualNetworkGatewaySku + } + gatewayType: virtualNetworkGatewayType + vpnType: vpnType_var + vpnClientConfiguration: !empty(vpnClientAddressPoolPrefix) ? vpnClientConfiguration : null + } + dependsOn: [ + virtualGatewayPublicIP + ] +} + +resource virtualNetworkGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualNetworkGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualNetworkGateway +} + +resource virtualNetworkGateway_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: virtualNetworkGatewayDiagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: virtualNetworkGatewayDiagnosticsLogs + } + scope: virtualNetworkGateway +} + +module virtualNetworkGateway_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VNetGateway-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualNetworkGateway.id + } +}] + +// ================// +// Outputs // +// ================// +@description('The resource group the virtual network gateway was deployed') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network gateway') +output name string = virtualNetworkGateway.name + +@description('The resource ID of the virtual network gateway') +output resourceId string = virtualNetworkGateway.id + +@description('Shows if the virtual network gateway is configured in active-active mode') +output activeActive bool = virtualNetworkGateway.properties.activeActive diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/readme.md b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/readme.md new file mode 100644 index 000000000..7c2ad18b9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/readme.md @@ -0,0 +1,153 @@ +# Virtual Network Gateways `[Microsoft.Network/virtualNetworkGateways]` + +This module deploys a virtual network gateway. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/publicIPAddresses` | 2021-05-01 | +| `Microsoft.Network/virtualNetworkGateways` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `name` | string | | | Specifies the Virtual Network Gateway name. | +| `virtualNetworkGatewaySku` | string | | `[Basic, VpnGw1, VpnGw2, VpnGw3, VpnGw1AZ, VpnGw2AZ, VpnGw3AZ, Standard, HighPerformance, UltraPerformance, ErGw1AZ, ErGw2AZ, ErGw3AZ]` | The Sku of the Gateway. | +| `virtualNetworkGatewayType` | string | | `[Vpn, ExpressRoute]` | Specifies the gateway type. E.g. VPN, ExpressRoute | +| `vNetResourceId` | string | | | Virtual Network resource ID | +| `vpnType` | string | `'RouteBased'` | `[PolicyBased, RouteBased]` | Specifies the VPN type | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `activeActive` | bool | `True` | | Value to specify if the Gateway should be deployed in active-active or active-passive configuration | +| `activeGatewayPipName` | string | `[format('{0}-pip2', parameters('name'))]` | | Specifies the name of the Public IP used by the Virtual Network Gateway when active-active configuration is required. If it's not provided, a '-pip' suffix will be appended to the gateway's name. | +| `asn` | int | `65815` | | ASN value | +| `clientRevokedCertThumbprint` | string | `''` | | Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet. | +| `clientRootCertData` | string | `''` | | Client root certificate data used to authenticate VPN clients. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `domainNameLabel` | array | `[]` | | DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com | +| `enableBgp` | bool | `True` | | Value to specify if BGP is enabled or not | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `gatewayPipName` | string | `[format('{0}-pip1', parameters('name'))]` | | Specifies the name of the Public IP used by the Virtual Network Gateway. If it's not provided, a '-pip' suffix will be appended to the gateway's name. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `publicIpdiagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `publicIpDiagnosticSettingsName` | string | `'diagnosticSettings'` | | The name of the diagnostic setting, if deployed. | +| `publicIPPrefixResourceId` | string | `''` | | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| `publicIpZones` | array | `[]` | | Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `virtualNetworkGatewaydiagnosticLogCategoriesToEnable` | array | `[GatewayDiagnosticLog, TunnelDiagnosticLog, RouteDiagnosticLog, IKEDiagnosticLog, P2SDiagnosticLog]` | `[GatewayDiagnosticLog, TunnelDiagnosticLog, RouteDiagnosticLog, IKEDiagnosticLog, P2SDiagnosticLog]` | The name of logs that will be streamed. | +| `virtualNetworkGatewayDiagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `vpnClientAddressPoolPrefix` | string | `''` | | The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network. | + + +### Parameter Usage: `subnets` + +The `subnets` parameter accepts a JSON Array of `subnet` objects to deploy to the Virtual Network. + +Here's an example of specifying a couple Subnets to deploy: + +```json +"subnets": { + "value": [ + { + "name": "app", + "properties": { + "addressPrefix": "10.1.0.0/24", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', 'app-nsg')]" + }, + "routeTable": { + "id": "[resourceId('Microsoft.Network/routeTables', 'app-udr')]" + } + } + }, + { + "name": "data", + "properties": { + "addressPrefix": "10.1.1.0/24" + } + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `activeActive` | bool | Shows if the virtual network gateway is configured in active-active mode | +| `name` | string | The name of the virtual network gateway | +| `resourceGroupName` | string | The resource group the virtual network gateway was deployed | +| `resourceId` | string | The resource ID of the virtual network gateway | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Publicipaddresses](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworkgateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworkGateways) diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/version.json b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworkGateways/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/carml/1.2.0/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b28fa1ee7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/.bicep/nested_rbac.bicep @@ -0,0 +1,70 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualNetwork.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualNetwork +}] diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json new file mode 100644 index 000000000..2d5064277 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/min.parameters.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-min-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/parameters.json new file mode 100644 index 000000000..9c66aa5de --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/parameters.json @@ -0,0 +1,93 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-x-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + }, + "subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.255.0/24" + }, + { + "name": "<>-az-subnet-x-001", + "addressPrefix": "10.0.0.0/24", + "networkSecurityGroupId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "serviceEndpoints": [ + { + "service": "Microsoft.Storage" + }, + { + "service": "Microsoft.Sql" + } + ], + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ], + "routeTableId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/routeTables/adp-<>-az-udr-x-001" + }, + { + "name": "<>-az-subnet-x-002", + "addressPrefix": "10.0.3.0/24", + "delegations": [ + { + "name": "netappDel", + "properties": { + "serviceName": "Microsoft.Netapp/volumes" + } + } + ] + }, + { + "name": "<>-az-subnet-x-003", + "addressPrefix": "10.0.6.0/24", + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + ] + }, + "dnsServers": { + "value": [ + "10.0.1.4", + "10.0.1.5" + ] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json b/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json new file mode 100644 index 000000000..f8faae317 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/.parameters/vnetPeering.parameters.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vnet-peer-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/24" + ] + }, + "subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.0.0/26" + } + ] + }, + "virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-peer01", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "useRemoteGateways": false, + "remotePeeringEnabled": true, + "remotePeeringName": "customName", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringAllowForwardedTraffic": true + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworks/deploy.bicep new file mode 100644 index 000000000..bd857be34 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/deploy.bicep @@ -0,0 +1,259 @@ +@description('Required. The Virtual Network (vNet) Name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. An Array of 1 or more IP Address Prefixes for the Virtual Network.') +param addressPrefixes array + +@description('Optional. An Array of subnets to deploy to the Virtual Network.') +param subnets array = [] + +@description('Optional. DNS Servers associated to the Virtual Network.') +param dnsServers array = [] + +@description('Optional. Resource ID of the DDoS protection plan to assign the VNET to. If it\'s left blank, DDoS protection will not be configured. If it\'s provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription.') +param ddosProtectionPlanId string = '' + +@description('Optional. Virtual Network Peerings configurations') +param virtualNetworkPeerings array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'VMProtectionAlerts' +]) +param diagnosticLogCategoriesToEnable array = [ + 'VMProtectionAlerts' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var dnsServers_var = { + dnsServers: array(dnsServers) +} +var ddosProtectionPlan = { + id: ddosProtectionPlanId +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressSpace: { + addressPrefixes: addressPrefixes + } + ddosProtectionPlan: !empty(ddosProtectionPlanId) ? ddosProtectionPlan : null + dhcpOptions: !empty(dnsServers) ? dnsServers_var : null + enableDdosProtection: !empty(ddosProtectionPlanId) + subnets: [for subnet in subnets: { + name: subnet.name + properties: { + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIpConfigurations: contains(subnet, 'applicationGatewayIpConfigurations') ? subnet.applicationGatewayIpConfigurations : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGateway: contains(subnet, 'natGatewayId') ? { + 'id': subnet.natGatewayId + } : json('null') + networkSecurityGroup: contains(subnet, 'networkSecurityGroupId') ? { + 'id': subnet.networkSecurityGroupId + } : json('null') + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : null + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : null + routeTable: contains(subnet, 'routeTableId') ? { + 'id': subnet.routeTableId + } : json('null') + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + } + }] + } +} + +//NOTE Start: ------------------------------------ +// The below module (virtualNetwork_subnets) is a duplicate of the child resource (subnets) defined in the parent module (virtualNetwork). +// The reason it exists so that deployment validation tests can be performed on the child module (subnets), in case that module needed to be deployed alone outside of this template. +// The reason for duplication is due to the current design for the (virtualNetworks) resource from Azure, where if the child module (subnets) does not exist within it, causes +// an issue, where the child resource (subnets) gets all of its properties removed, hence not as 'idempotent' as it should be. See https://github.com/Azure/azure-quickstart-templates/issues/2786 for more details. +// You can safely remove the below child module (virtualNetwork_subnets) in your consumption of the module (virtualNetworks) to reduce the template size and duplication. +//NOTE End : ------------------------------------ + +module virtualNetwork_subnets 'subnets/deploy.bicep' = [for (subnet, index) in subnets: { + name: '${uniqueString(deployment().name, location)}-subnet-${index}' + params: { + virtualNetworkName: virtualNetwork.name + name: subnet.name + addressPrefix: subnet.addressPrefix + addressPrefixes: contains(subnet, 'addressPrefixes') ? subnet.addressPrefixes : [] + applicationGatewayIpConfigurations: contains(subnet, 'applicationGatewayIpConfigurations') ? subnet.applicationGatewayIpConfigurations : [] + delegations: contains(subnet, 'delegations') ? subnet.delegations : [] + ipAllocations: contains(subnet, 'ipAllocations') ? subnet.ipAllocations : [] + natGatewayId: contains(subnet, 'natGatewayId') ? subnet.natGatewayId : '' + networkSecurityGroupId: contains(subnet, 'networkSecurityGroupId') ? subnet.networkSecurityGroupId : '' + privateEndpointNetworkPolicies: contains(subnet, 'privateEndpointNetworkPolicies') ? subnet.privateEndpointNetworkPolicies : '' + privateLinkServiceNetworkPolicies: contains(subnet, 'privateLinkServiceNetworkPolicies') ? subnet.privateLinkServiceNetworkPolicies : '' + roleAssignments: contains(subnet, 'roleAssignments') ? subnet.roleAssignments : [] + routeTableId: contains(subnet, 'routeTableId') ? subnet.routeTableId : '' + serviceEndpointPolicies: contains(subnet, 'serviceEndpointPolicies') ? subnet.serviceEndpointPolicies : [] + serviceEndpoints: contains(subnet, 'serviceEndpoints') ? subnet.serviceEndpoints : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +// Local to Remote peering +module virtualNetwork_peering_local 'virtualNetworkPeerings/deploy.bicep' = [for (peering, index) in virtualNetworkPeerings: { + name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-local-${index}' + params: { + localVnetName: virtualNetwork.name + remoteVirtualNetworkId: peering.remoteVirtualNetworkId + name: contains(peering, 'name') ? peering.name : '${name}-${last(split(peering.remoteVirtualNetworkId, '/'))}' + allowForwardedTraffic: contains(peering, 'allowForwardedTraffic') ? peering.allowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'allowGatewayTransit') ? peering.allowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'allowVirtualNetworkAccess') ? peering.allowVirtualNetworkAccess : true + doNotVerifyRemoteGateways: contains(peering, 'doNotVerifyRemoteGateways') ? peering.doNotVerifyRemoteGateways : true + useRemoteGateways: contains(peering, 'useRemoteGateways') ? peering.useRemoteGateways : false + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +// Remote to local peering (reverse) +module virtualNetwork_peering_remote 'virtualNetworkPeerings/deploy.bicep' = [for (peering, index) in virtualNetworkPeerings: if (contains(peering, 'remotePeeringEnabled') ? peering.remotePeeringEnabled == true : false) { + name: '${uniqueString(deployment().name, location)}-virtualNetworkPeering-remote-${index}' + scope: resourceGroup(split(peering.remoteVirtualNetworkId, '/')[2], split(peering.remoteVirtualNetworkId, '/')[4]) + params: { + localVnetName: last(split(peering.remoteVirtualNetworkId, '/')) + remoteVirtualNetworkId: virtualNetwork.id + name: contains(peering, 'remotePeeringName') ? peering.remotePeeringName : '${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}' + allowForwardedTraffic: contains(peering, 'remotePeeringAllowForwardedTraffic') ? peering.remotePeeringAllowForwardedTraffic : true + allowGatewayTransit: contains(peering, 'remotePeeringAllowGatewayTransit') ? peering.remotePeeringAllowGatewayTransit : false + allowVirtualNetworkAccess: contains(peering, 'remotePeeringAllowVirtualNetworkAccess') ? peering.remotePeeringAllowVirtualNetworkAccess : true + doNotVerifyRemoteGateways: contains(peering, 'remotePeeringDoNotVerifyRemoteGateways') ? peering.remotePeeringDoNotVerifyRemoteGateways : true + useRemoteGateways: contains(peering, 'remotePeeringUseRemoteGateways') ? peering.remotePeeringUseRemoteGateways : false + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +resource virtualNetwork_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualNetwork.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualNetwork +} + +resource virtualNetwork_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(diagnosticStorageAccountId) || !empty(diagnosticWorkspaceId) || !empty(diagnosticEventHubAuthorizationRuleId) || !empty(diagnosticEventHubName)) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: virtualNetwork +} + +module virtualNetwork_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VNet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualNetwork.id + } +}] + +@description('The resource group the virtual network was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the virtual network') +output resourceId string = virtualNetwork.id + +@description('The name of the virtual network') +output name string = virtualNetwork.name + +@description('The names of the deployed subnets') +output subnetNames array = [for subnet in subnets: subnet.name] + +@description('The resource IDs of the deployed subnets') +output subnetResourceIds array = [for subnet in subnets: az.resourceId('Microsoft.Network/virtualNetworks/subnets', name, subnet.name)] diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/readme.md b/carml/1.2.0/Microsoft.Network/virtualNetworks/readme.md new file mode 100644 index 000000000..daaa1ca6e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/readme.md @@ -0,0 +1,203 @@ +# Virtual Networks `[Microsoft.Network/virtualNetworks]` + +This template deploys a virtual network (vNet). + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Considerations](#Considerations) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/virtualNetworks` | 2021-05-01 | +| `Microsoft.Network/virtualNetworks/subnets` | 2021-05-01 | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `addressPrefixes` | array | An Array of 1 or more IP Address Prefixes for the Virtual Network. | +| `name` | string | The Virtual Network (vNet) Name. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `ddosProtectionPlanId` | string | `''` | | Resource ID of the DDoS protection plan to assign the VNET to. If it's left blank, DDoS protection will not be configured. If it's provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[VMProtectionAlerts]` | `[VMProtectionAlerts]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `dnsServers` | array | `[]` | | DNS Servers associated to the Virtual Network. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `subnets` | _[subnets](subnets/readme.md)_ array | `[]` | | An Array of subnets to deploy to the Virtual Network. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `virtualNetworkPeerings` | _[virtualNetworkPeerings](virtualNetworkPeerings/readme.md)_ array | `[]` | | Virtual Network Peerings configurations | + + +### Parameter Usage: `subnets` + +Below you can find an example for the subnet property's usage. For all remaining properties, please refer to the _[subnets](subnets/readme.md)_ readme. + +```json +"subnets": { + "value": [ + { + "name": "GatewaySubnet", + "addressPrefix": "10.0.255.0/24" + }, + { + "name": "<>-az-subnet-x-001", + "addressPrefix": "10.0.0.0/24", + "networkSecurityGroupId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/networkSecurityGroups/adp-<>-az-nsg-x-001", + "serviceEndpoints": [ + { + "service": "Microsoft.Storage" + }, + { + "service": "Microsoft.Sql" + } + ], + "routeTableId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/routeTables/adp-<>-az-udr-x-001", + "delegations": [ + { + "name": "netappDel", + "properties": { + "serviceName": "Microsoft.Netapp/volumes" + } + } + ], + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + ] +} +``` + +### Parameter Usage: `virtualNetworkPeerings` + +As the virtual network peering array allows you to deploy not only a one-way but also two-way peering (i.e reverse), you can use the following ***additional*** properties on top of what is documented in _[virtualNetworkPeerings](virtualNetworkPeerings/readme.md)_. + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `remotePeeringEnabled` | bool | `false` | | Optional. Set to true to also deploy the reverse peering for the configured remote virtual networks to the local network | +| `remotePeeringName` | string | `'${last(split(peering.remoteVirtualNetworkId, '/'))}-${name}'` | | Optional. The Name of Vnet Peering resource. If not provided, default value will be - | +| `remotePeeringAllowForwardedTraffic` | bool | `true` | | Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. | +| `remotePeeringAllowGatewayTransit` | bool | `false` | | Optional. If gateway links can be used in remote virtual networking to link to this virtual network. | +| `remotePeeringAllowVirtualNetworkAccess` | bool | `true` | | Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. | +| `remotePeeringDoNotVerifyRemoteGateways` | bool | `true` | | Optional. If we need to verify the provisioning state of the remote gateway. | +| `remotePeeringUseRemoteGateways` | bool | `false` | | Optional. If remote gateways can be used on this virtual network. If the flag is set to `true`, and allowGatewayTransit on local peering is also `true`, virtual network will use gateways of local virtual network for transit. Only one peering can have this flag set to `true`. This flag cannot be set if virtual network already has a gateway. | + +```json +"virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-peer01", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "useRemoteGateways": false, + "remotePeeringEnabled": true, + "remotePeeringName": "customName", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringAllowForwardedTraffic": true + } + ] +} +``` + +### Parameter Usage: `addressPrefixes` + +The `addressPrefixes` parameter accepts a JSON Array of string values containing the IP Address Prefixes for the Virtual Network (vNet). + +Here's an example of specifying a single Address Prefix: + +```json +"addressPrefixes": { + "value": [ + "10.1.0.0/16" + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Considerations + +The network security group and route table resources must reside in the same resource group as the virtual network. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network | +| `resourceGroupName` | string | The resource group the virtual network was deployed into | +| `resourceId` | string | The resource ID of the virtual network | +| `subnetNames` | array | The names of the deployed subnets | +| `subnetResourceIds` | array | The resource IDs of the deployed subnets | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks) +- [Virtualnetworks/Subnets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/subnets) +- [Virtualnetworks/Virtualnetworkpeerings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/virtualNetworkPeerings) diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..b70b981d8 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/.bicep/nested_rbac.bicep @@ -0,0 +1,70 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') +} + +resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-03-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(subnet.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: subnet +}] diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep new file mode 100644 index 000000000..f8fd00ce3 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep @@ -0,0 +1,124 @@ +@description('Optional. The Name of the subnet resource.') +param name string + +@description('Required. The name of the parent virtual network') +param virtualNetworkName string + +@description('Required. The address prefix for the subnet.') +param addressPrefix string + +@description('Optional. The resource ID of the network security group to assign to the subnet') +param networkSecurityGroupId string = '' + +@description('Optional. The resource ID of the route table to assign to the subnet') +param routeTableId string = '' + +@description('Optional. The service endpoints to enable on the subnet') +param serviceEndpoints array = [] + +@description('Optional. The delegations to enable on the subnet') +param delegations array = [] + +@description('Optional. The resource ID of the NAT Gateway to use for the subnet') +param natGatewayId string = '' + +@description('Optional. enable or disable apply network policies on private endpoint in the subnet.') +@allowed([ + 'Disabled' + 'Enabled' + '' +]) +param privateEndpointNetworkPolicies string = '' + +@description('Optional. enable or disable apply network policies on private link service in the subnet.') +@allowed([ + 'Disabled' + 'Enabled' + '' +]) +param privateLinkServiceNetworkPolicies string = '' + +@description('Optional. List of address prefixes for the subnet.') +param addressPrefixes array = [] + +@description('Optional. Application gateway IP configurations of virtual network resource.') +param applicationGatewayIpConfigurations array = [] + +@description('Optional. Array of IpAllocation which reference this subnet') +param ipAllocations array = [] + +@description('Optional. An array of service endpoint policies.') +param serviceEndpointPolicies array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: virtualNetworkName +} + +resource subnet 'Microsoft.Network/virtualNetworks/subnets@2021-05-01' = { + name: name + parent: virtualNetwork + properties: { + addressPrefix: addressPrefix + networkSecurityGroup: !empty(networkSecurityGroupId) ? { + id: networkSecurityGroupId + } : null + routeTable: !empty(routeTableId) ? { + id: routeTableId + } : null + natGateway: !empty(natGatewayId) ? { + id: natGatewayId + } : null + serviceEndpoints: serviceEndpoints + delegations: delegations + privateEndpointNetworkPolicies: !empty(privateEndpointNetworkPolicies) ? any(privateEndpointNetworkPolicies) : null + privateLinkServiceNetworkPolicies: !empty(privateLinkServiceNetworkPolicies) ? any(privateLinkServiceNetworkPolicies) : null + addressPrefixes: addressPrefixes + applicationGatewayIpConfigurations: applicationGatewayIpConfigurations + ipAllocations: ipAllocations + serviceEndpointPolicies: serviceEndpointPolicies + } +} + +module subnet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, resourceGroup().location)}-Subnet-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: subnet.id + } +}] + +@description('The resource group the virtual network peering was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network peering') +output name string = subnet.name + +@description('The resource ID of the virtual network peering') +output resourceId string = subnet.id + +@description('The address prefix for the subnet') +output subnetAddressPrefix string = subnet.properties.addressPrefix + +@description('List of address prefixes for the subnet') +output subnetAddressPrefixes array = !empty(addressPrefixes) ? subnet.properties.addressPrefixes : [] diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/readme.md b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/readme.md new file mode 100644 index 000000000..290795dfe --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/readme.md @@ -0,0 +1,115 @@ +# Virtual Network Subnets `[Microsoft.Network/virtualNetworks/subnets]` + +This module deploys a virtual network subnet. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Considerations](#Considerations) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/virtualNetworks/subnets` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `addressPrefix` | string | The address prefix for the subnet. | +| `virtualNetworkName` | string | The name of the parent virtual network | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefixes` | array | `[]` | | List of address prefixes for the subnet. | +| `applicationGatewayIpConfigurations` | array | `[]` | | Application gateway IP configurations of virtual network resource. | +| `delegations` | array | `[]` | | The delegations to enable on the subnet | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipAllocations` | array | `[]` | | Array of IpAllocation which reference this subnet | +| `name` | string | | | The Name of the subnet resource. | +| `natGatewayId` | string | `''` | | The resource ID of the NAT Gateway to use for the subnet | +| `networkSecurityGroupId` | string | `''` | | The resource ID of the network security group to assign to the subnet | +| `privateEndpointNetworkPolicies` | string | `''` | `[Disabled, Enabled, ]` | enable or disable apply network policies on private endpoint in the subnet. | +| `privateLinkServiceNetworkPolicies` | string | `''` | `[Disabled, Enabled, ]` | enable or disable apply network policies on private link service in the subnet. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `routeTableId` | string | `''` | | The resource ID of the route table to assign to the subnet | +| `serviceEndpointPolicies` | array | `[]` | | An array of service endpoint policies. | +| `serviceEndpoints` | array | `[]` | | The service endpoints to enable on the subnet | + + +### Parameter Usage: `delegations` + +```json +"delegations": [ + { + "name": "sqlMiDel", + "properties": { + "serviceName": "Microsoft.Sql/managedInstances" + } + } +] +``` + +### Parameter Usage: `serviceEndpoints` + +```json +"serviceEndpoints": [ + "Microsoft.EventHub", + "Microsoft.Sql", + "Microsoft.Storage", + "Microsoft.KeyVault" +] +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Considerations + +The `privateEndpointNetworkPolicies` property must be set to disabled for subnets that contain private endpoints. It confirms that NSGs rules will not apply to private endpoints (currently not supported, [reference](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-overview#limitations)). Default Value when not specified is "Enabled". + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network peering | +| `resourceGroupName` | string | The resource group the virtual network peering was deployed into | +| `resourceId` | string | The resource ID of the virtual network peering | +| `subnetAddressPrefix` | string | The address prefix for the subnet | +| `subnetAddressPrefixes` | array | List of address prefixes for the subnet | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualnetworks/Subnets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/subnets) diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/version.json b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/subnets/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/carml/1.2.0/Microsoft.Network/virtualNetworks/version.json b/carml/1.2.0/Microsoft.Network/virtualNetworks/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/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/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep new file mode 100644 index 000000000..8dfa90b89 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/deploy.bicep @@ -0,0 +1,66 @@ +@description('Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName') +param name string = '${localVnetName}-${last(split(remoteVirtualNetworkId, '/'))}' + +@description('Required. The Name of the Virtual Network to add the peering to.') +param localVnetName string + +@description('Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID') +param remoteVirtualNetworkId string + +@description('Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true') +param allowForwardedTraffic bool = true + +@description('Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false') +param allowGatewayTransit bool = false + +@description('Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true') +param allowVirtualNetworkAccess bool = true + +@description('Optional. If we need to verify the provisioning state of the remote gateway. Default is true') +param doNotVerifyRemoteGateways bool = true + +@description('Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false') +param useRemoteGateways bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' existing = { + name: localVnetName +} + +resource virtualNetworkPeering 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-05-01' = { + name: name + parent: virtualNetwork + properties: { + allowForwardedTraffic: allowForwardedTraffic + allowGatewayTransit: allowGatewayTransit + allowVirtualNetworkAccess: allowVirtualNetworkAccess + doNotVerifyRemoteGateways: doNotVerifyRemoteGateways + useRemoteGateways: useRemoteGateways + remoteVirtualNetwork: { + id: remoteVirtualNetworkId + } + } +} + +@description('The resource group the virtual network peering was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network peering') +output name string = virtualNetworkPeering.name + +@description('The resource ID of the virtual network peering') +output resourceId string = virtualNetworkPeering.id diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md b/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md new file mode 100644 index 000000000..46ac4e155 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/readme.md @@ -0,0 +1,55 @@ +# VirtualNetworkPeering `[Microsoft.Network/virtualNetworks/virtualNetworkPeerings]` + +This template deploys Virtual Network Peering. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualNetworks/virtualNetworkPeerings` | 2021-05-01 | + +### Resource dependency + +The following resources are required to be able to deploy this resource. + +- Local Virtual Network (Identified by the `localVnetName` parameter). +- Remote Virtual Network (Identified by the `remoteVirtualNetworkId` parameter) + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `localVnetName` | string | The Name of the Virtual Network to add the peering to. | +| `remoteVirtualNetworkId` | string | The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `allowForwardedTraffic` | bool | `True` | Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true | +| `allowGatewayTransit` | bool | `False` | If gateway links can be used in remote virtual networking to link to this virtual network. Default is false | +| `allowVirtualNetworkAccess` | bool | `True` | Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true | +| `doNotVerifyRemoteGateways` | bool | `True` | If we need to verify the provisioning state of the remote gateway. Default is true | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]` | The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName | +| `useRemoteGateways` | bool | `False` | If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual network peering | +| `resourceGroupName` | string | The resource group the virtual network peering was deployed into | +| `resourceId` | string | The resource ID of the virtual network peering | + +## Template references + +- [Virtualnetworks/Virtualnetworkpeerings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualNetworks/virtualNetworkPeerings) diff --git a/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/version.json b/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualNetworks/virtualNetworkPeerings/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/carml/1.2.0/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..702e277f7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualWans/.bicep/nested_rbac.bicep @@ -0,0 +1,55 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource virtualWan 'Microsoft.Network/virtualWans@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(virtualWan.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: virtualWan +}] diff --git a/carml/1.2.0/Microsoft.Network/virtualWans/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/virtualWans/.parameters/min.parameters.json new file mode 100644 index 000000000..badddffd7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualWans/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vw-min-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualWans/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/virtualWans/.parameters/parameters.json new file mode 100644 index 000000000..325af2525 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualWans/.parameters/parameters.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vw-x-001" + }, + "type": { + "value": "Basic" + }, + "allowBranchToBranchTraffic": { + "value": true + }, + "allowVnetToVnetTraffic": { + "value": true + }, + "disableVpnEncryption": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/virtualWans/deploy.bicep b/carml/1.2.0/Microsoft.Network/virtualWans/deploy.bicep new file mode 100644 index 000000000..ed9577d22 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualWans/deploy.bicep @@ -0,0 +1,91 @@ +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Required. Name of the Virtual WAN.') +param name string + +@description('Optional. The type of the Virtual WAN.') +@allowed([ + 'Standard' + 'Basic' +]) +param type string = 'Standard' + +@description('Optional. True if branch to branch traffic is allowed.') +param allowBranchToBranchTraffic bool = false + +@description('Optional. True if VNET to VNET traffic is allowed. ') +param allowVnetToVnetTraffic bool = false + +@description('Optional. VPN encryption to be disabled or not.') +param disableVpnEncryption bool = false + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource virtualWan 'Microsoft.Network/virtualWans@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + allowBranchToBranchTraffic: allowBranchToBranchTraffic + allowVnetToVnetTraffic: allowVnetToVnetTraffic ? allowVnetToVnetTraffic : null + disableVpnEncryption: disableVpnEncryption + type: type + } +} + +resource virtualWan_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${virtualWan.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: virtualWan +} + +module virtualWan_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VWan-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: virtualWan.id + } +}] + +@description('The name of the virtual WAN') +output name string = virtualWan.name + +@description('The resource ID of the virtual WAN') +output resourceId string = virtualWan.id + +@description('The resource group the virtual WAN was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/virtualWans/readme.md b/carml/1.2.0/Microsoft.Network/virtualWans/readme.md new file mode 100644 index 000000000..dc9b92914 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualWans/readme.md @@ -0,0 +1,96 @@ +# Virtual WANs `[Microsoft.Network/virtualWans]` + +This template deploys a virtual WAN. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/virtualWans` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the Virtual WAN. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBranchToBranchTraffic` | bool | `False` | | True if branch to branch traffic is allowed. | +| `allowVnetToVnetTraffic` | bool | `False` | | True if VNET to VNET traffic is allowed. | +| `disableVpnEncryption` | bool | `False` | | VPN encryption to be disabled or not. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[resourceGroup().location]` | | Location where all resources will be created. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `type` | string | `'Standard'` | `[Standard, Basic]` | The type of the Virtual WAN. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the virtual WAN | +| `resourceGroupName` | string | The resource group the virtual WAN was deployed into | +| `resourceId` | string | The resource ID of the virtual WAN | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Virtualwans](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/virtualWans) diff --git a/carml/1.2.0/Microsoft.Network/virtualWans/version.json b/carml/1.2.0/Microsoft.Network/virtualWans/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/virtualWans/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/carml/1.2.0/Microsoft.Network/vpnGateways/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/vpnGateways/.parameters/min.parameters.json new file mode 100644 index 000000000..4ed3a736e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/.parameters/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": "<>-az-vpngw-min-001" + }, + "virtualHubResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-min-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/vpnGateways/.parameters/parameters.json new file mode 100644 index 000000000..af4f1eca8 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/.parameters/parameters.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vpngw-x-001" + }, + "virtualHubResourceId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-x-001" + }, + "bgpSettings": { + "value": { + "asn": 65515, + "peerWeight": 0 + } + }, + "connections": { + "value": [ + { + "name": "Connection-<>-az-vsite-x-001", + "connectionBandwidth": 10, + "enableBgp": true, + "routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-x-001/hubRouteTables/defaultRouteTable" + }, + "propagatedRouteTables": { + "labels": [ + "default" + ], + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/<>-az-vhub-x-001/hubRouteTables/defaultRouteTable" + } + ] + }, + "vnetRoutes": { + "staticRoutes": [] + } + }, + "remoteVpnSiteResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/vpnSites/<>-az-vsite-x-001" + } + ] + }, + "natRules": { + "value": [ + { + "name": "natRule1", + "internalMappings": [ + { + "addressSpace": "10.4.0.0/24" + } + ], + "externalMappings": [ + { + "addressSpace": "192.168.21.0/24" + } + ], + "type": "Static", + "mode": "EgressSnat" + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/connections/deploy.bicep b/carml/1.2.0/Microsoft.Network/vpnGateways/connections/deploy.bicep new file mode 100644 index 000000000..6464b6440 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/connections/deploy.bicep @@ -0,0 +1,102 @@ +@description('Required. The name of the VPN connection.') +param name string + +@description('Required. The name of the VPN gateway this VPN connection is associated with.') +param vpnGatewayName string + +@description('Optional. The IPSec policies to be considered by this connection.') +param ipsecPolicies array = [] + +@description('Optional. The traffic selector policies to be considered by this connection.') +param trafficSelectorPolicies array = [] + +@description('Optional. List of all VPN site link connections to the gateway.') +param vpnLinkConnections array = [] + +@description('Optional. Routing configuration indicating the associated and propagated route tables for this connection.') +param routingConfiguration object = {} + +@description('Optional. Enable policy-based traffic selectors.') +param usePolicyBasedTrafficSelectors bool = false + +@description('Optional. Use local Azure IP to initiate connection.') +param useLocalAzureIpAddress bool = false + +@description('Optional. Enable rate limiting.') +param enableRateLimiting bool = false + +@description('Optional. Enable internet security.') +param enableInternetSecurity bool = false + +@description('Optional. Enable BGP flag.') +param enableBgp bool = false + +@description('Optional. Routing weight for VPN connection.') +param routingWeight int = 0 + +@description('Optional. Expected bandwidth in MBPS.') +param connectionBandwidth int = 10 + +@description('Optional. Gateway connection protocol.') +@allowed([ + 'IKEv1' + 'IKEv2' +]) +param vpnConnectionProtocolType string = 'IKEv2' + +@description('Optional. SharedKey for the VPN connection.') +param sharedKey string = '' + +@description('Optional. Reference to a VPN site to link to') +param remoteVpnSiteResourceId string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-05-01' existing = { + name: vpnGatewayName +} + +resource vpnConnection 'Microsoft.Network/vpnGateways/vpnConnections@2021-05-01' = { + name: name + parent: vpnGateway + properties: { + connectionBandwidth: connectionBandwidth + enableBgp: enableBgp + enableInternetSecurity: enableInternetSecurity + enableRateLimiting: enableRateLimiting + ipsecPolicies: ipsecPolicies + remoteVpnSite: !empty(remoteVpnSiteResourceId) ? { + id: remoteVpnSiteResourceId + } : null + routingConfiguration: routingConfiguration + routingWeight: routingWeight + sharedKey: sharedKey + trafficSelectorPolicies: trafficSelectorPolicies + useLocalAzureIpAddress: useLocalAzureIpAddress + usePolicyBasedTrafficSelectors: usePolicyBasedTrafficSelectors + vpnConnectionProtocolType: vpnConnectionProtocolType + vpnLinkConnections: vpnLinkConnections + } +} + +@description('The name of the VPN connection') +output name string = vpnConnection.name + +@description('The resource ID of the VPN connection') +output resourceId string = vpnConnection.id + +@description('The name of the resource group the VPN connection was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/connections/readme.md b/carml/1.2.0/Microsoft.Network/vpnGateways/connections/readme.md new file mode 100644 index 000000000..364fa4930 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/connections/readme.md @@ -0,0 +1,79 @@ +# VPN Gateways Connections `[Microsoft.Network/vpnGateways/connections]` + +This module deploys VPN Gateways Connections. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/vpnGateways/vpnConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN connection. | +| `vpnGatewayName` | string | The name of the VPN gateway this VPN connection is associated with. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `connectionBandwidth` | int | `10` | | Expected bandwidth in MBPS. | +| `enableBgp` | bool | `False` | | Enable BGP flag. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableInternetSecurity` | bool | `False` | | Enable internet security. | +| `enableRateLimiting` | bool | `False` | | Enable rate limiting. | +| `ipsecPolicies` | array | `[]` | | The IPSec policies to be considered by this connection. | +| `remoteVpnSiteResourceId` | string | `''` | | Reference to a VPN site to link to | +| `routingConfiguration` | object | `{object}` | | Routing configuration indicating the associated and propagated route tables for this connection. | +| `routingWeight` | int | `0` | | Routing weight for VPN connection. | +| `sharedKey` | string | `''` | | SharedKey for the VPN connection. | +| `trafficSelectorPolicies` | array | `[]` | | The traffic selector policies to be considered by this connection. | +| `useLocalAzureIpAddress` | bool | `False` | | Use local Azure IP to initiate connection. | +| `usePolicyBasedTrafficSelectors` | bool | `False` | | Enable policy-based traffic selectors. | +| `vpnConnectionProtocolType` | string | `'IKEv2'` | `[IKEv1, IKEv2]` | Gateway connection protocol. | +| `vpnLinkConnections` | array | `[]` | | List of all VPN site link connections to the gateway. | + + +### Parameter Usage: `routingConfiguration` + +```json +"routingConfiguration": { + "associatedRouteTable": { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/SampleVirtualHub/hubRouteTables/defaultRouteTable" + }, + "propagatedRouteTables": { + "labels": [ + "default" + ], + "ids": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualHubs/SampleVirtualHub/hubRouteTables/defaultRouteTable" + } + ] + }, + "vnetRoutes": { + "staticRoutes": [] + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN connection | +| `resourceGroupName` | string | The name of the resource group the VPN connection was deployed into | +| `resourceId` | string | The resource ID of the VPN connection | + +## Template references + +- [Vpngateways/Vpnconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/vpnConnections) diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/connections/version.json b/carml/1.2.0/Microsoft.Network/vpnGateways/connections/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/connections/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/deploy.bicep b/carml/1.2.0/Microsoft.Network/vpnGateways/deploy.bicep new file mode 100644 index 000000000..436c0cea3 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/deploy.bicep @@ -0,0 +1,119 @@ +@description('Required. Name of the VPN gateway') +param name string + +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Optional. The connections to create in the VPN gateway') +param connections array = [] + +@description('Optional. List of all the NAT Rules to associate with the gateway.') +param natRules array = [] + +@description('Required. The resource ID of a virtual Hub to connect to. Note: The virtual Hub and Gateway must be deployed into the same location.') +param virtualHubResourceId string + +@description('Optional. BGP settings details.') +param bgpSettings object = {} + +@description('Optional. Enable BGP routes translation for NAT on this VPN gateway.') +param enableBgpRouteTranslationForNat bool = false + +@description('Optional. Enable routing preference property for the public IP interface of the VPN gateway.') +param isRoutingPreferenceInternet bool = false + +@description('Optional. The scale unit for this VPN gateway.') +param vpnGatewayScaleUnit int = 2 + +@description('Optional. Tags of the resource.') +param tags object = {} + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + bgpSettings: bgpSettings + enableBgpRouteTranslationForNat: enableBgpRouteTranslationForNat + isRoutingPreferenceInternet: isRoutingPreferenceInternet + vpnGatewayScaleUnit: vpnGatewayScaleUnit + virtualHub: { + id: virtualHubResourceId + } + } +} + +resource vpnGateway_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vpnGateway.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vpnGateway +} + +module vpnGateway_natRules 'natRules/deploy.bicep' = [for (natRule, index) in natRules: { + name: '${deployment().name}-NATRule-${index}' + params: { + name: natRule.name + vpnGatewayName: vpnGateway.name + externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] + internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] + ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' + mode: contains(natRule, 'mode') ? natRule.mode : '' + type: contains(natRule, 'type') ? natRule.type : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +module vpnGateway_connections 'connections/deploy.bicep' = [for (connection, index) in connections: { + name: '${deployment().name}-Connection-${index}' + params: { + name: connection.name + vpnGatewayName: vpnGateway.name + connectionBandwidth: contains(connection, 'connectionBandwidth') ? connection.connectionBandwidth : 10 + enableBgp: contains(connection, 'enableBgp') ? connection.enableBgp : false + enableInternetSecurity: contains(connection, 'enableInternetSecurity') ? connection.enableInternetSecurity : false + remoteVpnSiteResourceId: contains(connection, 'remoteVpnSiteResourceId') ? connection.remoteVpnSiteResourceId : '' + enableRateLimiting: contains(connection, 'enableRateLimiting') ? connection.enableRateLimiting : false + routingConfiguration: contains(connection, 'routingConfiguration') ? connection.routingConfiguration : {} + routingWeight: contains(connection, 'routingWeight') ? connection.routingWeight : 0 + sharedKey: contains(connection, 'sharedKey') ? connection.sharedKey : '' + useLocalAzureIpAddress: contains(connection, 'useLocalAzureIpAddress') ? connection.useLocalAzureIpAddress : false + usePolicyBasedTrafficSelectors: contains(connection, 'usePolicyBasedTrafficSelectors') ? connection.usePolicyBasedTrafficSelectors : false + vpnConnectionProtocolType: contains(connection, 'vpnConnectionProtocolType') ? connection.vpnConnectionProtocolType : 'IKEv2' + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the VPN gateway') +output name string = vpnGateway.name + +@description('The resource ID of the VPN gateway') +output resourceId string = vpnGateway.id + +@description('The name of the resource group the VPN gateway was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/deploy.bicep b/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/deploy.bicep new file mode 100644 index 000000000..05c117ae5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/deploy.bicep @@ -0,0 +1,70 @@ +@description('Required. The name of the NAT rule.') +param name string + +@description('Required. The name of the VPN gateway this NAT rule is associated with.') +param vpnGatewayName string + +@description('Optional. An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range.') +param externalMappings array = [] + +@description('Optional. An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range.') +param internalMappings array = [] + +@description('Optional. A NAT rule must be configured to a specific VPN Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both VPN Gateway instances.') +param ipConfigurationId string = '' + +@description('Optional. The type of NAT rule for VPN NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub\'s site-to-site VPN gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub\'s Site-to-site VPN gateway.') +@allowed([ + '' + 'EgressSnat' + 'IngressSnat' +]) +param mode string = '' + +@description('Optional. The type of NAT rule for VPN NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability.') +@allowed([ + '' + 'Dynamic' + 'Static' +]) +param type string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnGateway 'Microsoft.Network/vpnGateways@2021-05-01' existing = { + name: vpnGatewayName +} + +resource natRule 'Microsoft.Network/vpnGateways/natRules@2021-05-01' = { + name: name + parent: vpnGateway + properties: { + externalMappings: externalMappings + internalMappings: internalMappings + ipConfigurationId: !empty(ipConfigurationId) ? ipConfigurationId : null + mode: !empty(mode) ? any(mode) : null + type: !empty(type) ? any(type) : null + } +} + +@description('The name of the NAT rule') +output name string = natRule.name + +@description('The resource ID of the NAT rule') +output resourceId string = natRule.id + +@description('The name of the resource group the NAT rule was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/readme.md b/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/readme.md new file mode 100644 index 000000000..383a3b01a --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/readme.md @@ -0,0 +1,47 @@ +# VPN Gateways NATRules `[Microsoft.Network/vpnGateways/natRules]` + +This module deploys VPN Gateways NATRules + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/vpnGateways/natRules` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT rule. | +| `vpnGatewayName` | string | The name of the VPN gateway this NAT rule is associated with. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `externalMappings` | array | `[]` | | An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range. | +| `internalMappings` | array | `[]` | | An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range. | +| `ipConfigurationId` | string | `''` | | A NAT rule must be configured to a specific VPN Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both VPN Gateway instances. | +| `mode` | string | `''` | `[, EgressSnat, IngressSnat]` | The type of NAT rule for VPN NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub's site-to-site VPN gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub's Site-to-site VPN gateway. | +| `type` | string | `''` | `[, Dynamic, Static]` | The type of NAT rule for VPN NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT rule | +| `resourceGroupName` | string | The name of the resource group the NAT rule was deployed into | +| `resourceId` | string | The resource ID of the NAT rule | + +## Template references + +- [Vpngateways/Natrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/natRules) diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/version.json b/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/natRules/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/readme.md b/carml/1.2.0/Microsoft.Network/vpnGateways/readme.md new file mode 100644 index 000000000..02005d8a3 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/readme.md @@ -0,0 +1,109 @@ +# VPN Gateways `[Microsoft.Network/vpnGateways]` + +This module deploys VPN Gateways. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Network/vpnGateways` | 2021-05-01 | +| `Microsoft.Network/vpnGateways/natRules` | 2021-05-01 | +| `Microsoft.Network/vpnGateways/vpnConnections` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the VPN gateway | +| `virtualHubResourceId` | string | The resource ID of a virtual Hub to connect to. Note: The virtual Hub and Gateway must be deployed into the same location. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `bgpSettings` | object | `{object}` | | BGP settings details. | +| `connections` | _[connections](connections/readme.md)_ array | `[]` | | The connections to create in the VPN gateway | +| `enableBgpRouteTranslationForNat` | bool | `False` | | Enable BGP routes translation for NAT on this VPN gateway. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `isRoutingPreferenceInternet` | bool | `False` | | Enable routing preference property for the public IP interface of the VPN gateway. | +| `location` | string | `[resourceGroup().location]` | | Location where all resources will be created. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `natRules` | _[natRules](natRules/readme.md)_ array | `[]` | | List of all the NAT Rules to associate with the gateway. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `vpnGatewayScaleUnit` | int | `2` | | The scale unit for this VPN gateway. | + + +### Parameter Usage: + +### Parameter Usage: `bgpSettings` + +```json +"bgpSettings": { + "asn": 65515, + "peerWeight": 0, + "bgpPeeringAddresses": [ + { + "ipconfigurationId": "Instance0", + "defaultBgpIpAddresses": [ + "10.0.0.12" + ], + "customBgpIpAddresses": [], + "tunnelIpAddresses": [ + "20.84.35.53", + "10.0.0.4" + ] + }, + { + "ipconfigurationId": "Instance1", + "defaultBgpIpAddresses": [ + "10.0.0.13" + ], + "customBgpIpAddresses": [], + "tunnelIpAddresses": [ + "20.84.34.225", + "10.0.0.5" + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN gateway | +| `resourceGroupName` | string | The name of the resource group the VPN gateway was deployed into | +| `resourceId` | string | The resource ID of the VPN gateway | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Vpngateways](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways) +- [Vpngateways/Natrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/natRules) +- [Vpngateways/Vpnconnections](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnGateways/vpnConnections) diff --git a/carml/1.2.0/Microsoft.Network/vpnGateways/version.json b/carml/1.2.0/Microsoft.Network/vpnGateways/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnGateways/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Network/vpnSites/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Network/vpnSites/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..4452aae54 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnSites/.bicep/nested_rbac.bicep @@ -0,0 +1,37 @@ +param principalIds array +param principalType string = '' +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource vpnSite 'Microsoft.Network/vpnSites@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(vpnSite.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: vpnSite +}] diff --git a/carml/1.2.0/Microsoft.Network/vpnSites/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Network/vpnSites/.parameters/min.parameters.json new file mode 100644 index 000000000..24791e033 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnSites/.parameters/min.parameters.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vSite-min-001" + }, + "addressPrefixes": { + "value": [ + "10.0.0.0/16" + ] + }, + "ipAddress": { + "value": "1.2.3.4" + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/apd-<>-az-vw-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/vpnSites/.parameters/parameters.json b/carml/1.2.0/Microsoft.Network/vpnSites/.parameters/parameters.json new file mode 100644 index 000000000..39ec5e30c --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnSites/.parameters/parameters.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-vSite-x-001" + }, + "tags": { + "value": { + "tagA": "valueA", + "tagB": "valueB" + } + }, + "deviceProperties": { + "value": { + "linkSpeedInMbps": 0 + } + }, + "virtualWanId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualWans/apd-<>-az-vw-x-001" + }, + "vpnSiteLinks": { + "value": [ + { + "name": "<>-az-vSite-x-001", + "properties": { + "bgpProperties": { + "asn": 65010, + "bgpPeeringAddress": "1.1.1.1" + }, + "ipAddress": "1.2.3.4", + "linkProperties": { + "linkProviderName": "contoso", + "linkSpeedInMbps": 5 + } + } + }, + { + "name": "Link1", + "properties": { + "bgpProperties": { + "asn": 65020, + "bgpPeeringAddress": "192.168.1.0" + }, + "ipAddress": "2.2.2.2", + "linkProperties": { + "linkProviderName": "contoso", + "linkSpeedInMbps": 5 + } + } + } + ] + }, + "o365Policy": { + "value": { + "breakOutCategories": { + "optimize": true, + "allow": true, + "default": true + } + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Network/vpnSites/deploy.bicep b/carml/1.2.0/Microsoft.Network/vpnSites/deploy.bicep new file mode 100644 index 000000000..1dd53818e --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnSites/deploy.bicep @@ -0,0 +1,105 @@ +@description('Required. Name of the VPN Site.') +param name string + +@description('Required. Resource ID of the virtual WAN to link to') +param virtualWanId string + +@description('Optional. Location where all resources will be created.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. An array of IP address ranges that can be used by subnets of the virtual network. Must be provided if no bgpProperties or VPNSiteLinks are configured.') +param addressPrefixes array = [] + +@description('Optional. BGP settings details. Must be provided if no addressPrefixes or VPNSiteLinks are configured. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead.') +param bgpProperties object = {} + +@description('Optional. List of properties of the device.') +param deviceProperties object = {} + +@description('Optional. The IP-address for the VPN-site. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead.') +param ipAddress string = '' + +@description('Optional. IsSecuritySite flag') +param isSecuritySite bool = false + +@description('Optional. The Office365 breakout policy.') +param o365Policy object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. List of all VPN site links.') +param vpnSiteLinks array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource vpnSite 'Microsoft.Network/vpnSites@2021-05-01' = { + name: name + location: location + tags: tags + properties: { + addressSpace: !empty(addressPrefixes) ? { + addressPrefixes: addressPrefixes + } : null + bgpProperties: !empty(bgpProperties) ? bgpProperties : null + deviceProperties: !empty(deviceProperties) ? deviceProperties : null + ipAddress: !empty(ipAddress) ? ipAddress : null + isSecuritySite: isSecuritySite + o365Policy: !empty(o365Policy) ? o365Policy : null + virtualWan: { + id: virtualWanId + } + vpnSiteLinks: !empty(vpnSiteLinks) ? vpnSiteLinks : null + } +} + +resource vpnSite_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${vpnSite.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: vpnSite +} + +module vpnSite_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-VWan-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: vpnSite.id + } +}] + +@description('The name of the VPN site') +output name string = vpnSite.name + +@description('The resource ID of the VPN site') +output resourceId string = vpnSite.id + +@description('The resource group the VPN site was deployed into') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Network/vpnSites/readme.md b/carml/1.2.0/Microsoft.Network/vpnSites/readme.md new file mode 100644 index 000000000..7b7e9a1d3 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnSites/readme.md @@ -0,0 +1,165 @@ +# VPN Sites `[Microsoft.Network/vpnSites]` + +This module deploys a VPN Site. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Network/vpnSites` | 2021-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the VPN Site. | +| `virtualWanId` | string | Resource ID of the virtual WAN to link to | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `addressPrefixes` | array | `[]` | | An array of IP address ranges that can be used by subnets of the virtual network. Must be provided if no bgpProperties or VPNSiteLinks are configured. | +| `bgpProperties` | object | `{object}` | | BGP settings details. Must be provided if no addressPrefixes or VPNSiteLinks are configured. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead. | +| `deviceProperties` | object | `{object}` | | List of properties of the device. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `ipAddress` | string | `''` | | The IP-address for the VPN-site. Note: This is a deprecated property, please use the corresponding VpnSiteLinks property instead. | +| `isSecuritySite` | bool | `False` | | IsSecuritySite flag | +| `location` | string | `[resourceGroup().location]` | | Location where all resources will be created. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `o365Policy` | object | `{object}` | | The Office365 breakout policy. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the resource. | +| `vpnSiteLinks` | array | `[]` | | List of all VPN site links. | + + +### Parameter Usage `o365Policy` + +```json +"o365Policy": { + "value": { + "breakOutCategories": { + "optimize": true, + "allow": true, + "default": true + } + } +} +``` + +### Parameter Usage `deviceProperties` + +```json +"deviceProperties": { + "value": { + "deviceModel": "morty", + "deviceVendor": "contoso", + "linkSpeedInMbps": 0 + } +} +``` + +### Parameter Usage `bgpProperties` + +The BGP properties. Note: This is a deprecated property, please use the corresponding `VpnSiteLinks` property instead. + +```json +"bgpProperties": { + "value": { + "asn": 65010, + "bgpPeeringAddress": "1.1.1.1", + "peerWeight": 0 + } +} +``` + +### Parameter Usage `vpnSiteLinks` + +An array of links. Should be used instead of the top-level `ipAddress` & `bgpProperties` properties. If using links, one default link with same name and properties as VpnSite itself is mandatory. + +```json +"vpnSiteLinks": { + "value": [ + { + "name": "<>-az-vSite-x-001", + "properties": { + "bgpProperties": { + "asn": 65010, + "bgpPeeringAddress": "1.1.1.1" + }, + "ipAddress": "1.2.3.4", + "linkProperties": { + "linkProviderName": "contoso", + "linkSpeedInMbps": 5 + } + } + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the VPN site | +| `resourceGroupName` | string | The resource group the VPN site was deployed into | +| `resourceId` | string | The resource ID of the VPN site | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Vpnsites](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/vpnSites) diff --git a/carml/1.2.0/Microsoft.Network/vpnSites/version.json b/carml/1.2.0/Microsoft.Network/vpnSites/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Network/vpnSites/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Resources/deploymentScripts/.parameters/cli.parameters.json b/carml/1.2.0/Microsoft.Resources/deploymentScripts/.parameters/cli.parameters.json new file mode 100644 index 000000000..e3e775a93 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/deploymentScripts/.parameters/cli.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": "<>-az-ds-cli-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "kind": { + "value": "AzureCLI" + }, + "azCliVersion": { + "value": "2.15.0" + }, + "scriptContent": { + "value": "echo \"Hello from inside the script\"" + }, + "retentionInterval": { + "value": "P1D" + }, + "runOnce": { + "value": false + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT30M" + } + } +} diff --git a/carml/1.2.0/Microsoft.Resources/deploymentScripts/.parameters/ps.parameters.json b/carml/1.2.0/Microsoft.Resources/deploymentScripts/.parameters/ps.parameters.json new file mode 100644 index 000000000..9f780f49a --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/deploymentScripts/.parameters/ps.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": "<>-az-ds-ps-001" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "kind": { + "value": "AzurePowerShell" + }, + "azPowerShellVersion": { + "value": "3.0" + }, + "scriptContent": { + "value": "Write-Host 'Running PowerShell from template'" + }, + "retentionInterval": { + "value": "P1D" + }, + "runOnce": { + "value": false + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT30M" + } + } +} diff --git a/carml/1.2.0/Microsoft.Resources/deploymentScripts/deploy.bicep b/carml/1.2.0/Microsoft.Resources/deploymentScripts/deploy.bicep new file mode 100644 index 000000000..65de5b3b0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/deploymentScripts/deploy.bicep @@ -0,0 +1,136 @@ +@description('Required. Display name of the script to be run.') +param name string + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Type of the script. AzurePowerShell, AzureCLI.') +@allowed([ + 'AzurePowerShell' + 'AzureCLI' +]) +param kind string = 'AzurePowerShell' + +@description('Optional. Azure PowerShell module version to be used.') +param azPowerShellVersion string = '3.0' + +@description('Optional. Azure CLI module version to be used.') +param azCliVersion string = '' + +@description('Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead.') +param scriptContent string = '' + +@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead.') +param primaryScriptUri string = '' + +@description('Optional. The environment variables to pass over to the script. Must have a \'name\' and a \'value\' or a \'secretValue\' property.') +param environmentVariables array = [] + +@description('Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent).') +param supportingScriptUris array = [] + +@description('Optional. Command-line arguments to pass to the script. Arguments are separated by spaces.') +param arguments string = '' + +@description('Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week).') +param retentionInterval string = 'P1D' + +@description('Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once.') +param runOnce bool = false + +@description('Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled).') +@allowed([ + 'Always' + 'OnSuccess' + 'OnExpiration' +]) +param cleanupPreference string = 'Always' + +@description('Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a \'containerGroupName\' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use \'containerGroupName\' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. \'containerGroupName\' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed.') +param containerGroupName string = '' + +@description('Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; \'PT30M\' - 30 minutes; \'P5D\' - 5 days; \'P1Y\' 1 year.') +param timeout string = 'PT1H' + +@description('Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +var containerSettings = { + containerGroupName: containerGroupName +} + +var identityType = !empty(userAssignedIdentities) ? 'UserAssigned' : 'None' + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource deploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: name + location: location + tags: tags + identity: identity + kind: any(kind) + properties: { + azPowerShellVersion: kind == 'AzurePowerShell' ? azPowerShellVersion : null + azCliVersion: kind == 'AzureCLI' ? azCliVersion : null + containerSettings: empty(containerGroupName) ? null : containerSettings + arguments: arguments + environmentVariables: empty(environmentVariables) ? null : environmentVariables + scriptContent: empty(scriptContent) ? null : scriptContent + primaryScriptUri: empty(primaryScriptUri) ? null : primaryScriptUri + supportingScriptUris: empty(supportingScriptUris) ? null : supportingScriptUris + cleanupPreference: cleanupPreference + forceUpdateTag: runOnce ? resourceGroup().name : baseTime + retentionInterval: retentionInterval + timeout: timeout + } +} + +resource deploymentScript_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${deploymentScript.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: deploymentScript +} + +@description('The resource ID of the deployment script') +output resourceId string = deploymentScript.id + +@description('The resource group the deployment script was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The name of the deployment script') +output name string = deploymentScript.name diff --git a/carml/1.2.0/Microsoft.Resources/deploymentScripts/readme.md b/carml/1.2.0/Microsoft.Resources/deploymentScripts/readme.md new file mode 100644 index 000000000..a82e6c9dc --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/deploymentScripts/readme.md @@ -0,0 +1,100 @@ +# Deployment Scripts `[Microsoft.Resources/deploymentScripts]` + +This module deploys a deployment script. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Resources/deploymentScripts` | 2020-10-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Display name of the script to be run. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `arguments` | string | `''` | | Command-line arguments to pass to the script. Arguments are separated by spaces. | +| `azCliVersion` | string | `''` | | Azure CLI module version to be used. | +| `azPowerShellVersion` | string | `'3.0'` | | Azure PowerShell module version to be used. | +| `cleanupPreference` | string | `'Always'` | `[Always, OnSuccess, OnExpiration]` | The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled). | +| `containerGroupName` | string | `''` | | Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `environmentVariables` | array | `[]` | | The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property. | +| `kind` | string | `'AzurePowerShell'` | `[AzurePowerShell, AzureCLI]` | Type of the script. AzurePowerShell, AzureCLI. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `primaryScriptUri` | string | `''` | | Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead. | +| `retentionInterval` | string | `'P1D'` | | Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week). | +| `runOnce` | bool | `False` | | When set to false, script will run every time the template is deployed. When set to true, the script will only run once. | +| `scriptContent` | string | `''` | | Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead. | +| `supportingScriptUris` | array | `[]` | | List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent). | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeout` | string | `'PT1H'` | | Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('yyyy-MM-dd-HH-mm-ss')]` | Do not provide a value! This date value is used to make sure the script run every time the template is deployed. | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployment script | +| `resourceGroupName` | string | The resource group the deployment script was deployed into | +| `resourceId` | string | The resource ID of the deployment script | + +## Considerations + +This module requires a User Assigned Identity (MSI, managed service identity) to exist, and this MSI has to have contributor rights on the subscription - that allows the Deployment Script to create the required Storage Account and the Azure Container Instance. + +## Template references + +- [Deploymentscripts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2020-10-01/deploymentScripts) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) diff --git a/carml/1.2.0/Microsoft.Resources/deploymentScripts/version.json b/carml/1.2.0/Microsoft.Resources/deploymentScripts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/deploymentScripts/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/carml/1.2.0/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep b/carml/1.2.0/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep new file mode 100644 index 000000000..c3f891565 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/resourceGroups/.bicep/nested_lock.bicep @@ -0,0 +1,31 @@ +@description('Optional. The name of the Lock') +param name string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Set lock level.') +param level string = 'NotSpecified' + +var lockNotes = { + CanNotDelete: 'Cannot delete resource or child resources.' + ReadOnly: 'Cannot modify the resource or child resources.' +} + +var lockName = empty(name) ? '${level}-lock' : name + +resource lock 'Microsoft.Authorization/locks@2017-04-01' = if (level != 'NotSpecified') { + name: lockName + properties: { + level: level + notes: lockNotes[level] + } +} + +@description('The resource ID of the lock') +output resourceId string = lock.id + +@description('The name of the lock') +output name string = lock.name diff --git a/carml/1.2.0/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..0fe91115a --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/resourceGroups/.bicep/nested_rbac.bicep @@ -0,0 +1,208 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'AcrDelete': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11') + 'AcrImageSigner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f') + 'AcrPull': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + 'AcrPush': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec') + 'AcrQuarantineReader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04') + 'AcrQuarantineWriter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608') + 'API Management Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c') + 'API Management Service Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61') + 'API Management Service Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d') + 'App Configuration Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b') + 'App Configuration Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071') + 'Application Insights Component Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e') + 'Application Insights Snapshot Debugger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b') + 'Attestation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e') + 'Attestation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3') + 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') + 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') + 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Azure Connected Machine Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7') + 'Azure Connected Machine Resource Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302') + 'Azure Digital Twins Owner (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe') + 'Azure Digital Twins Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3') + 'Azure Event Hubs Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec') + 'Azure Event Hubs Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde') + 'Azure Event Hubs Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975') + 'Azure Kubernetes Service Cluster Admin Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8') + 'Azure Kubernetes Service Cluster User Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f') + 'Azure Kubernetes Service Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8') + 'Azure Maps Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204') + 'Azure Maps Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa') + 'Azure Sentinel Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade') + 'Azure Sentinel Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb') + 'Azure Sentinel Responder': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056') + 'Azure Service Bus Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419') + 'Azure Service Bus Data Receiver': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') + 'Azure Service Bus Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') + 'Azure Stack Registration Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + 'Billing Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64') + 'BizTalk Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342') + 'Blockchain Member Node Access (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24') + 'Blueprint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4') + 'Blueprint Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090') + 'CDN Endpoint Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45') + 'CDN Endpoint Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd') + 'CDN Profile Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432') + 'CDN Profile Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af') + 'Classic Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f') + 'Classic Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25') + 'Classic Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d') + 'Classic Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb') + 'ClearDB MySQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe') + 'Cognitive Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68') + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3') + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f') + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c') + 'Cognitive Services Custom Vision Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73') + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b') + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c') + 'Cognitive Services QnA Maker Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025') + 'Cognitive Services QnA Maker Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126') + 'Cognitive Services User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Cosmos DB Account Reader Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8') + 'Cosmos DB Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa') + 'CosmosBackupOperator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb') + 'Cost Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430') + 'Cost Management Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3') + 'Data Box Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5') + 'Data Box Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027') + 'Data Factory Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5') + 'Data Lake Analytics Developer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88') + 'Data Purger': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90') + 'Desktop Virtualization User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314') + 'DocumentDB Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450') + 'EventGrid EventSubscription Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443') + 'EventGrid EventSubscription Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405') + 'Experimentation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c') + 'Experimentation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c') + 'Experimentation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1') + 'FHIR Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd') + 'FHIR Data Exporter': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843') + 'FHIR Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508') + 'FHIR Data Writer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913') + 'Graph Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9') + 'HDInsight Cluster Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a') + 'HDInsight Domain Services Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c') + 'Hierarchy Settings Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d') + 'Hybrid Server Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb') + 'Hybrid Server Resource Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624') + 'Integration Service Environment Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8') + 'Integration Service Environment Developer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec') + 'Intelligent Systems Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e') + 'Key Vault Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395') + 'Knowledge Consumer': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c') + 'Kubernetes Cluster - Azure Arc Onboarding': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41') + 'Lab Creator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Logic App Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 'Managed Services Registration assignment Delete ': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46') + 'Management Group Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c') + 'Management Group Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d') + 'Marketplace Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + 'New Relic APM Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237') + 'Object Understanding Account Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745') + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Policy Insights Data Writer (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84') + 'Private DNS Zone Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Redis Cache Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17') + 'Remote Rendering Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e') + 'Remote Rendering Client': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Scheduler Job Collections Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94') + 'Search Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0') + 'Security Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd') + 'Security Assessment Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5') + 'Security Manager (Legacy)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10') + 'Security Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4') + 'SignalR AccessKey Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e') + 'SignalR Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Site Recovery Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149') + 'Spatial Anchors Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827') + 'Spatial Anchors Account Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c') + 'Spatial Anchors Account Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413') + 'SQL DB Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec') + 'SQL Managed Instance Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d') + 'SQL Security Manager': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3') + 'SQL Server Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Support Request Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e') + 'Tag Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f') + 'Traffic Manager Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + 'Web Plan Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b') + 'Website Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772') + 'Workbook Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad') + 'Workbook Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d') +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(last(split(resourceId, '/')), principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } +}] diff --git a/carml/1.2.0/Microsoft.Resources/resourceGroups/.parameters/parameters.json b/carml/1.2.0/Microsoft.Resources/resourceGroups/.parameters/parameters.json new file mode 100644 index 000000000..3be494132 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/resourceGroups/.parameters/parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-rg-x-001" + }, + "tags": { + "value": { + "Test": "Yes" + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.Resources/resourceGroups/deploy.bicep b/carml/1.2.0/Microsoft.Resources/resourceGroups/deploy.bicep new file mode 100644 index 000000000..f14994442 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/resourceGroups/deploy.bicep @@ -0,0 +1,71 @@ +targetScope = 'subscription' + +@description('Required. The name of the Resource Group') +param name string + +@description('Optional. Location of the Resource Group. It uses the deployment\'s location when not provided.') +param location string = deployment().location + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Tags of the storage account resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2019-05-01' = { + location: location + name: name + tags: tags + properties: {} +} + +module resourceGroup_lock '.bicep/nested_lock.bicep' = if (lock != 'NotSpecified') { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-RG-${lock}-Lock' + params: { + name: '${resourceGroup.name}-${lock}-lock' + level: lock + } +} + +module resourceGroup_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-RG-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: resourceGroup.id + } + scope: resourceGroup +}] + +@description('The name of the resource group') +output name string = resourceGroup.name + +@description('The resource ID of the resource group') +output resourceId string = resourceGroup.id diff --git a/carml/1.2.0/Microsoft.Resources/resourceGroups/readme.md b/carml/1.2.0/Microsoft.Resources/resourceGroups/readme.md new file mode 100644 index 000000000..f6059b713 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/resourceGroups/readme.md @@ -0,0 +1,96 @@ +# Resource Groups `[Microsoft.Resources/resourceGroups]` + +This module deploys a resource group. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Considerations](#Considerations) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Resources/resourceGroups` | 2019-05-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the Resource Group | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | | Location of the Resource Group. It uses the deployment's location when not provided. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `tags` | object | `{object}` | | Tags of the storage account resource. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Considerations + +This module requires a User Assigned Identity (MSI, managed service identity) to exist, and this MSI has to have contributor rights on the subscription - that allows the Deployment Script to create the required Storage Account and the Azure Container Instance. + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the resource group | +| `resourceId` | string | The resource ID of the resource group | + +## Template references + +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Resourcegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-05-01/resourceGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/carml/1.2.0/Microsoft.Resources/resourceGroups/version.json b/carml/1.2.0/Microsoft.Resources/resourceGroups/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/resourceGroups/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/carml/1.2.0/Microsoft.Resources/tags/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Resources/tags/.parameters/min.parameters.json new file mode 100644 index 000000000..d90c44f3f --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/.parameters/min.parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": {} +} diff --git a/carml/1.2.0/Microsoft.Resources/tags/.parameters/rg.parameters.json b/carml/1.2.0/Microsoft.Resources/tags/.parameters/rg.parameters.json new file mode 100644 index 000000000..a90e2e5b2 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/.parameters/rg.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "onlyUpdate": { + "value": false + }, + "tags": { + "value": { + "Test": "Yes", + "TestToo": "No" + } + }, + "resourceGroupName": { + "value": "validation-rg" + } + } +} diff --git a/carml/1.2.0/Microsoft.Resources/tags/.parameters/sub.parameters.json b/carml/1.2.0/Microsoft.Resources/tags/.parameters/sub.parameters.json new file mode 100644 index 000000000..840b23ba6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/.parameters/sub.parameters.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "onlyUpdate": { + "value": true + }, + "tags": { + "value": { + "Test": "Yes", + "TestToo": "No" + } + } + } +} diff --git a/carml/1.2.0/Microsoft.Resources/tags/deploy.bicep b/carml/1.2.0/Microsoft.Resources/tags/deploy.bicep new file mode 100644 index 000000000..be034dda2 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/deploy.bicep @@ -0,0 +1,58 @@ +targetScope = 'subscription' + +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@description('Optional. Name of the Resource Group to assign the tags to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription.') +param resourceGroupName string = '' + +@description('Optional. Subscription ID of the subscription to assign the tags to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription.') +param subscriptionId string = subscription().id + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module tags_sub 'subscriptions/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { + name: '${deployment().name}-Tags-Sub' + params: { + onlyUpdate: onlyUpdate + tags: tags + location: location + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module tags_rg 'resourceGroups/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { + name: '${deployment().name}-Tags-RG' + scope: resourceGroup(resourceGroupName) + params: { + onlyUpdate: onlyUpdate + tags: tags + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@description('The name of the tags resource') +output name string = (!empty(resourceGroupName) && !empty(subscriptionId)) ? tags_rg.outputs.name : tags_sub.outputs.name + +@description('The applied tags') +output tags object = (!empty(resourceGroupName) && !empty(subscriptionId)) ? tags_rg.outputs.tags : tags_sub.outputs.tags diff --git a/carml/1.2.0/Microsoft.Resources/tags/readme.md b/carml/1.2.0/Microsoft.Resources/tags/readme.md new file mode 100644 index 000000000..b5665a5eb --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/readme.md @@ -0,0 +1,57 @@ +# Resources Tags `[Microsoft.Resources/tags]` + +This module deploys Resources Tags on a subscription or resource group scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `onlyUpdate` | bool | `False` | Instead of overwriting the existing tags, combine them with the new tags | +| `resourceGroupName` | string | `''` | Name of the Resource Group to assign the tags to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription. | +| `subscriptionId` | string | `[subscription().id]` | Subscription ID of the subscription to assign the tags to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided tags to the subscription. | +| `tags` | object | `{object}` | Tags for the resource group. If not provided, removes existing tags | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep new file mode 100644 index 000000000..0f3301f97 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/.bicep/readTags.bicep @@ -0,0 +1,9 @@ +@description('Optional. The name of the tags resource.') +param name string = 'default' + +resource tags 'Microsoft.Resources/tags@2019-10-01' existing = { + name: name +} + +@description('Tags currently applied to the subscription level') +output existingTags object = contains(tags.properties, 'tags') ? tags.properties.tags : {} diff --git a/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/deploy.bicep b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/deploy.bicep new file mode 100644 index 000000000..81993a0cd --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/deploy.bicep @@ -0,0 +1,48 @@ +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module readTags '.bicep/readTags.bicep' = if (onlyUpdate) { + name: '${deployment().name}-ReadTags' +} + +var newTags = (onlyUpdate) ? union(readTags.outputs.existingTags, tags) : tags + +resource tag 'Microsoft.Resources/tags@2019-10-01' = { + name: name + properties: { + tags: newTags + } +} + +@description('The name of the tags resource') +output name string = tag.name + +@description('The resourceId of the resource group the tags were applied to') +output resourceId string = resourceGroup().id + +@description('The name of the resource group the tags were applied to') +output resourceGroupName string = resourceGroup().name + +@description('The applied tags') +output tags object = newTags diff --git a/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/readme.md b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/readme.md new file mode 100644 index 000000000..43279ae11 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/readme.md @@ -0,0 +1,57 @@ +# Resources Tags ResourceGroups `[Microsoft.Resources/tags/resourceGroups]` + +This module deploys Resources Tags on a resource group scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the tags resource. | +| `onlyUpdate` | bool | `False` | Instead of overwriting the existing tags, combine them with the new tags | +| `tags` | object | `{object}` | Tags for the resource group. If not provided, removes existing tags | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `resourceGroupName` | string | The name of the resource group the tags were applied to | +| `resourceId` | string | The resourceId of the resource group the tags were applied to | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/version.json b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/resourceGroups/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep new file mode 100644 index 000000000..65b245725 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/.bicep/readTags.bicep @@ -0,0 +1,11 @@ +targetScope = 'subscription' + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +resource tags 'Microsoft.Resources/tags@2019-10-01' existing = { + name: name +} + +@description('Tags currently applied to the subscription level') +output existingTags object = contains(tags.properties, 'tags') ? tags.properties.tags : {} diff --git a/carml/1.2.0/Microsoft.Resources/tags/subscriptions/deploy.bicep b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/deploy.bicep new file mode 100644 index 000000000..7424c11bc --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/deploy.bicep @@ -0,0 +1,48 @@ +targetScope = 'subscription' + +@description('Optional. Tags for the resource group. If not provided, removes existing tags') +param tags object = {} + +@description('Optional. The name of the tags resource.') +param name string = 'default' + +@description('Optional. Instead of overwriting the existing tags, combine them with the new tags') +param onlyUpdate bool = false + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +module readTags '.bicep/readTags.bicep' = if (onlyUpdate) { + name: '${deployment().name}-ReadTags' +} + +var newTags = (onlyUpdate) ? union(readTags.outputs.existingTags, tags) : tags + +resource tag 'Microsoft.Resources/tags@2019-10-01' = { + name: name + properties: { + tags: newTags + } +} + +@description('The name of the tags resource') +output name string = tag.name + +@description('The applied tags') +output tags object = newTags diff --git a/carml/1.2.0/Microsoft.Resources/tags/subscriptions/readme.md b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/readme.md new file mode 100644 index 000000000..38fb51f39 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/readme.md @@ -0,0 +1,56 @@ +# Resources Tags Subscriptions `[Microsoft.Resources/tags/subscriptions]` + +This module deploys Resources Tags on a subscription scope. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Resources/tags` | 2019-10-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `location` | string | `[deployment().location]` | Location deployment metadata. | +| `name` | string | `'default'` | The name of the tags resource. | +| `onlyUpdate` | bool | `False` | Instead of overwriting the existing tags, combine them with the new tags | +| `tags` | object | `{object}` | Tags for the resource group. If not provided, removes existing tags | + + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the tags resource | +| `tags` | object | The applied tags | + +## Template references + +- [Tags](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Resources/2019-10-01/tags) diff --git a/carml/1.2.0/Microsoft.Resources/tags/subscriptions/version.json b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/subscriptions/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Resources/tags/version.json b/carml/1.2.0/Microsoft.Resources/tags/version.json new file mode 100644 index 000000000..41f66cc99 --- /dev/null +++ b/carml/1.2.0/Microsoft.Resources/tags/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 000000000..75fa03bcd --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,49 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? ((empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds)) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } + + resource privateDnsZoneGroups 'privateDnsZoneGroups@2021-02-01' = { + name: 'default' + properties: { + privateDnsZoneConfigs: [for privateDnsZoneResourceId in privateEndpoint_var.privateDnsZoneResourceIds: { + name: last(split(privateDnsZoneResourceId, '/')) + properties: { + privateDnsZoneId: privateDnsZoneResourceId + } + }] + } + } +} diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c1fb27d3a --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/.bicep/nested_rbac.bicep @@ -0,0 +1,80 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(storageAccount.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: storageAccount +}] diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json new file mode 100644 index 000000000..30ac50db6 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/min.parameters.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "allowBlobPublicAccess": { + "value": false + } + } +} diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/nfs.parameters.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/nfs.parameters.json new file mode 100644 index 000000000..7ae90dbda --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/nfs.parameters.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsax002" + }, + "storageAccountSku": { + "value": "Premium_LRS" + }, + "storageAccountKind": { + "value": "FileStorage" + }, + "allowBlobPublicAccess": { + "value": false + }, + "supportsHttpsTrafficOnly": { + "value": false + }, + "fileServices": { + "value": { + "shares": [ + { + "name": "nfsfileshare", + "enabledProtocols": "NFS" + } + ] + } + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/parameters.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/parameters.json new file mode 100644 index 000000000..95d58e294 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/parameters.json @@ -0,0 +1,189 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>azsax001" + }, + "storageAccountSku": { + "value": "Standard_LRS" + }, + "allowBlobPublicAccess": { + "value": false + }, + "publicNetworkAccess": { + "value": "Disabled" + }, + "requireInfrastructureEncryption": { + "value": true + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "blob" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "table" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "queue" + }, + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", + "service": "file" + } + ] + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "action": "Allow" + } + ], + "ipRules": [ + { + "action": "Allow", + "value": "1.1.1.1" + } + ] + } + }, + "blobServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "containers": [ + { + "name": "avdscripts", + "publicAccess": "None", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "archivecontainer", + "publicAccess": "None", + "enableWORM": true, + "WORMRetention": 666, + "allowProtectedAppendWrites": false + } + ] + } + }, + "fileServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "shares": [ + { + "name": "avdprofiles", + "shareQuota": "5120", + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "avdprofiles2", + "shareQuota": "5120" + } + ] + } + }, + "tableServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "tables": [ + "table1", + "table2" + ] + } + }, + "queueServices": { + "value": { + "diagnosticLogsRetentionInDays": 7, + "diagnosticStorageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", + "diagnosticWorkspaceId": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001", + "diagnosticEventHubAuthorizationRuleId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey", + "diagnosticEventHubName": "adp-<>-az-evh-x-001", + "queues": [ + { + "name": "queue1", + "metadata": {}, + "roleAssignments": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + { + "name": "queue2", + "metadata": {} + } + ] + } + }, + "systemAssignedIdentity": { + "value": true + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json new file mode 100644 index 000000000..c411287f9 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/.parameters/v1.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "storageAccountKind": { + "value": "Storage" + }, + "allowBlobPublicAccess": { + "value": false + } + } +} diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..ffd787fab --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/.bicep/nested_rbac.bicep @@ -0,0 +1,71 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(container.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: container +}] diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep new file mode 100644 index 000000000..45b19fdbe --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/deploy.bicep @@ -0,0 +1,89 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. The name of the storage container to deploy') +param name string + +@description('Optional. Name of the immutable policy.') +param immutabilityPolicyName string = 'default' + +@allowed([ + 'Container' + 'Blob' + 'None' +]) +@description('Optional. Specifies whether data in the container may be accessed publicly and the level of access.') +param publicAccess string = 'None' + +@description('Optional. Configure immutability policy.') +param immutabilityPolicyProperties object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + } +} + +resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' = { + name: name + parent: storageAccount::blobServices + properties: { + publicAccess: publicAccess + } +} + +module immutabilityPolicy 'immutabilityPolicies/deploy.bicep' = if (!empty(immutabilityPolicyProperties)) { + name: immutabilityPolicyName + params: { + storageAccountName: storageAccount.name + blobServicesName: storageAccount::blobServices.name + containerName: container.name + immutabilityPeriodSinceCreationInDays: contains(immutabilityPolicyProperties, 'immutabilityPeriodSinceCreationInDays') ? immutabilityPolicyProperties.immutabilityPeriodSinceCreationInDays : 365 + allowProtectedAppendWrites: contains(immutabilityPolicyProperties, 'allowProtectedAppendWrites') ? immutabilityPolicyProperties.allowProtectedAppendWrites : true + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +module container_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: container.id + } +}] + +@description('The name of the deployed container') +output name string = container.name + +@description('The resource ID of the deployed container') +output resourceId string = container.id + +@description('The resource group of the deployed container') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep new file mode 100644 index 000000000..a7c87d255 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/deploy.bicep @@ -0,0 +1,63 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. Name of the blob service.') +param blobServicesName string = 'default' + +@description('Required. Name of the container to apply the policy to') +param containerName string + +@description('Optional. Name of the immutable policy.') +param name string = 'default' + +@description('Optional. The immutability period for the blobs in the container since the policy creation, in days.') +param immutabilityPeriodSinceCreationInDays int = 365 + +@description('Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API') +param allowProtectedAppendWrites bool = true + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource blobServices 'blobServices@2021-06-01' existing = { + name: blobServicesName + + resource container 'containers@2019-06-01' existing = { + name: containerName + } + } +} + +resource immutabilityPolicy 'Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2019-06-01' = { + name: name + parent: storageAccount::blobServices::container + properties: { + immutabilityPeriodSinceCreationInDays: immutabilityPeriodSinceCreationInDays + allowProtectedAppendWrites: allowProtectedAppendWrites + } +} + +@description('The name of the deployed immutability policy.') +output name string = immutabilityPolicy.name + +@description('The resource ID of the deployed immutability policy.') +output resourceId string = immutabilityPolicy.id + +@description('The resource group of the deployed immutability policy.') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md new file mode 100644 index 000000000..62d201778 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/readme.md @@ -0,0 +1,46 @@ +# Blob Container Immutability Policy `[Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies]` + +This module deploys an Immutability Policy for a blob container + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `containerName` | string | Name of the container to apply the policy to | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `allowProtectedAppendWrites` | bool | `True` | This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API | +| `blobServicesName` | string | `'default'` | Name of the blob service. | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `immutabilityPeriodSinceCreationInDays` | int | `365` | The immutability period for the blobs in the container since the policy creation, in days. | +| `name` | string | `'default'` | Name of the immutable policy. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed immutability policy. | +| `resourceGroupName` | string | The resource group of the deployed immutability policy. | +| `resourceId` | string | The resource ID of the deployed immutability policy. | + +## Template references + +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies/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/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md new file mode 100644 index 000000000..93371cb97 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/readme.md @@ -0,0 +1,77 @@ +# Storage Account Container `[Microsoft.Storage/storageAccounts/blobServices/containers]` + +This module deploys a blob container + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the storage container to deploy | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `blobServicesName` | string | `'default'` | | Name of the blob service. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `immutabilityPolicyName` | string | `'default'` | | Name of the immutable policy. | +| `immutabilityPolicyProperties` | object | `{object}` | | Configure immutability policy. | +| `publicAccess` | string | `'None'` | `[Container, Blob, None]` | Specifies whether data in the container may be accessed publicly and the level of access. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed container | +| `resourceGroupName` | string | The resource group of the deployed container | +| `resourceId` | string | The resource ID of the deployed container | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/containers/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/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep new file mode 100644 index 000000000..b6afb1a82 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/deploy.bicep @@ -0,0 +1,143 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the blob service') +param name string = 'default' + +@description('Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service.') +param deleteRetentionPolicy bool = true + +@description('Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365.') +param deleteRetentionPolicyDays int = 7 + +@description('Optional. Automatic Snapshot is enabled if set to true.') +param automaticSnapshotPolicyEnabled bool = false + +@description('Optional. Blob containers to create.') +param containers array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource blobServices 'Microsoft.Storage/storageAccounts/blobServices@2021-06-01' = { + name: name + parent: storageAccount + properties: { + deleteRetentionPolicy: { + enabled: deleteRetentionPolicy + days: deleteRetentionPolicyDays + } + automaticSnapshotPolicyEnabled: automaticSnapshotPolicyEnabled + } +} + +resource blobServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: blobServices +} + +module blobServices_container 'containers/deploy.bicep' = [for (container, index) in containers: { + name: '${deployment().name}-Container-${index}' + params: { + storageAccountName: storageAccount.name + blobServicesName: blobServices.name + name: container.name + publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None' + roleAssignments: contains(container, 'roleAssignments') ? container.roleAssignments : [] + immutabilityPolicyProperties: contains(container, 'immutabilityPolicyProperties') ? container.immutabilityPolicyProperties : {} + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the deployed blob service') +output name string = blobServices.name + +@description('The resource ID of the deployed blob service') +output resourceId string = blobServices.id + +@description('The name of the deployed blob service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/readme.md new file mode 100644 index 000000000..202404d37 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/readme.md @@ -0,0 +1,62 @@ +# Storage Account blob services `[Microsoft.Storage/storageAccounts/blobServices]` + +This module can be used to deploy a blob service into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/blobServices` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `automaticSnapshotPolicyEnabled` | bool | `False` | | Automatic Snapshot is enabled if set to true. | +| `containers` | _[containers](containers/readme.md)_ array | `[]` | | Blob containers to create. | +| `deleteRetentionPolicy` | bool | `True` | | Indicates whether DeleteRetentionPolicy is enabled for the Blob service. | +| `deleteRetentionPolicyDays` | int | `7` | | Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the blob service | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed blob service | +| `resourceGroupName` | string | The name of the deployed blob service | +| `resourceId` | string | The resource ID of the deployed blob service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Blobservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/blobServices) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/blobServices/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/carml/1.2.0/Microsoft.Storage/storageAccounts/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/deploy.bicep new file mode 100644 index 000000000..8b9ca4d1e --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/deploy.bicep @@ -0,0 +1,358 @@ +@maxLength(24) +@description('Optional. Name of the Storage Account. Autogenerated with a unique string if not provided.') +param name string = '' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@allowed([ + 'Storage' + 'StorageV2' + 'BlobStorage' + 'FileStorage' + 'BlockBlobStorage' +]) +@description('Optional. Type of Storage Account to create.') +param storageAccountKind string = 'StorageV2' + +@allowed([ + 'Standard_LRS' + 'Standard_GRS' + 'Standard_RAGRS' + 'Standard_ZRS' + 'Premium_LRS' + 'Premium_ZRS' + 'Standard_GZRS' + 'Standard_RAGZRS' +]) +@description('Optional. Storage Account Sku Name.') +param storageAccountSku string = 'Standard_GRS' + +@allowed([ + 'Hot' + 'Cool' +]) +@description('Optional. Storage Account Access Tier.') +param storageAccountAccessTier string = 'Hot' + +@description('Optional. Provides the identity based authentication settings for Azure Files.') +param azureFilesIdentityBasedAuthentication object = {} + +@description('Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible') +param privateEndpoints array = [] + +@description('Optional. The Storage Account ManagementPolicies Rules.') +param managementPolicyRules array = [] + +@description('Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny') +param networkAcls object = {} + +@description('Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true.') +param requireInfrastructureEncryption bool = true + +@description('Optional. Blob service and containers to deploy') +param blobServices object = {} + +@description('Optional. File service and shares to deploy') +param fileServices object = {} + +@description('Optional. Queue service and queues to create.') +param queueServices object = {} + +@description('Optional. Table service and tables to create.') +param tableServices object = {} + +@description('Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false.') +param allowBlobPublicAccess bool = false + +@allowed([ + 'TLS1_0' + 'TLS1_1' + 'TLS1_2' +]) +@description('Optional. Set the minimum TLS version on request to storage.') +param minimumTlsVersion string = 'TLS1_2' + +@description('Optional. If true, enables Hierarchical Namespace for the storage account') +param enableHierarchicalNamespace bool = false + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules.') +param basetime string = utcNow('u') + +@allowed([ + 'Enabled' + 'Disabled' +]) + +@description('Optional. Enable or disallow public network access to Storage Account..') +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Allows HTTPS traffic only to storage service if sets to true.') +param supportsHttpsTrafficOnly bool = true + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var maxNameLength = 24 +var uniqueStorageNameUntrim = '${uniqueString('Storage Account${basetime}')}' +var uniqueStorageName = length(uniqueStorageNameUntrim) > maxNameLength ? substring(uniqueStorageNameUntrim, 0, maxNameLength) : uniqueStorageNameUntrim + +var supportsBlobService = storageAccountKind == 'BlockBlobStorage' || storageAccountKind == 'BlobStorage' || storageAccountKind == 'StorageV2' || storageAccountKind == 'Storage' +var supportsFileService = storageAccountKind == 'FileStorage' || storageAccountKind == 'StorageV2' || storageAccountKind == 'Storage' + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = { + name: !empty(name) ? name : uniqueStorageName + location: location + kind: storageAccountKind + sku: { + name: storageAccountSku + } + identity: identity + tags: tags + properties: { + encryption: { + keySource: 'Microsoft.Storage' + services: { + blob: supportsBlobService ? { + enabled: true + } : null + file: supportsFileService ? { + enabled: true + } : null + } + requireInfrastructureEncryption: storageAccountKind != 'Storage' ? requireInfrastructureEncryption : null + } + accessTier: storageAccountKind != 'Storage' ? storageAccountAccessTier : null + supportsHttpsTrafficOnly: supportsHttpsTrafficOnly + isHnsEnabled: enableHierarchicalNamespace ? enableHierarchicalNamespace : null + minimumTlsVersion: minimumTlsVersion + networkAcls: !empty(networkAcls) ? { + bypass: !empty(networkAcls) ? networkAcls.bypass : null + defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null + virtualNetworkRules: (!empty(networkAcls) && contains(networkAcls, 'virtualNetworkRules')) ? networkAcls.virtualNetworkRules : [] + ipRules: (!empty(networkAcls) && contains(networkAcls, 'ipRules')) ? networkAcls.ipRules : [] + } : null + allowBlobPublicAccess: allowBlobPublicAccess + publicNetworkAccess: publicNetworkAccess + azureFilesIdentityBasedAuthentication: !empty(azureFilesIdentityBasedAuthentication) ? azureFilesIdentityBasedAuthentication : null + } +} + +resource storageAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + } + scope: storageAccount +} + +resource storageAccount_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${storageAccount.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: storageAccount +} + +module storageAccount_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-Storage-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: storageAccount.id + } +}] + +module storageAccount_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (endpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-Storage-PrivateEndpoints-${index}' + params: { + privateEndpointResourceId: storageAccount.id + privateEndpointVnetLocation: !empty(privateEndpoints) ? reference(split(endpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location : 'dummy' + privateEndpointObj: endpoint + tags: tags + } +}] + +// Lifecycle Policy +module storageAccount_managementPolicies 'managementPolicies/deploy.bicep' = if (!empty(managementPolicyRules)) { + name: '${uniqueString(deployment().name, location)}-Storage-ManagementPolicies' + params: { + storageAccountName: storageAccount.name + rules: managementPolicyRules + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +// Containers +module storageAccount_blobServices 'blobServices/deploy.bicep' = if (!empty(blobServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-BlobServices' + params: { + storageAccountName: storageAccount.name + containers: contains(blobServices, 'containers') ? blobServices.containers : [] + automaticSnapshotPolicyEnabled: contains(blobServices, 'automaticSnapshotPolicyEnabled') ? blobServices.automaticSnapshotPolicyEnabled : false + deleteRetentionPolicy: contains(blobServices, 'deleteRetentionPolicy') ? blobServices.deleteRetentionPolicy : true + deleteRetentionPolicyDays: contains(blobServices, 'deleteRetentionPolicyDays') ? blobServices.deleteRetentionPolicyDays : 7 + diagnosticLogsRetentionInDays: contains(blobServices, 'diagnosticLogsRetentionInDays') ? blobServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(blobServices, 'diagnosticStorageAccountId') ? blobServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(blobServices, 'diagnosticEventHubAuthorizationRuleId') ? blobServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(blobServices, 'diagnosticEventHubName') ? blobServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(blobServices, 'diagnosticLogCategoriesToEnable') ? blobServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(blobServices, 'diagnosticMetricsToEnable') ? blobServices.diagnosticMetricsToEnable : [] + diagnosticWorkspaceId: contains(blobServices, 'diagnosticWorkspaceId') ? blobServices.diagnosticWorkspaceId : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +// File Shares +module storageAccount_fileServices 'fileServices/deploy.bicep' = if (!empty(fileServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-FileServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(fileServices, 'diagnosticLogsRetentionInDays') ? fileServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(fileServices, 'diagnosticStorageAccountId') ? fileServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(fileServices, 'diagnosticEventHubAuthorizationRuleId') ? fileServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(fileServices, 'diagnosticEventHubName') ? fileServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(fileServices, 'diagnosticLogCategoriesToEnable') ? fileServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(fileServices, 'diagnosticMetricsToEnable') ? fileServices.diagnosticMetricsToEnable : [] + protocolSettings: contains(fileServices, 'protocolSettings') ? fileServices.protocolSettings : {} + shareDeleteRetentionPolicy: contains(fileServices, 'shareDeleteRetentionPolicy') ? fileServices.shareDeleteRetentionPolicy : { + enabled: true + days: 7 + } + shares: contains(fileServices, 'shares') ? fileServices.shares : [] + diagnosticWorkspaceId: contains(fileServices, 'diagnosticWorkspaceId') ? fileServices.diagnosticWorkspaceId : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +// Queue +module storageAccount_queueServices 'queueServices/deploy.bicep' = if (!empty(queueServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-QueueServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(queueServices, 'diagnosticLogsRetentionInDays') ? queueServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(queueServices, 'diagnosticStorageAccountId') ? queueServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(queueServices, 'diagnosticEventHubAuthorizationRuleId') ? queueServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(queueServices, 'diagnosticEventHubName') ? queueServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(queueServices, 'diagnosticLogCategoriesToEnable') ? queueServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(queueServices, 'diagnosticMetricsToEnable') ? queueServices.diagnosticMetricsToEnable : [] + queues: contains(queueServices, 'queues') ? queueServices.queues : [] + diagnosticWorkspaceId: contains(queueServices, 'diagnosticWorkspaceId') ? queueServices.diagnosticWorkspaceId : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +// Table +module storageAccount_tableServices 'tableServices/deploy.bicep' = if (!empty(tableServices)) { + name: '${uniqueString(deployment().name, location)}-Storage-TableServices' + params: { + storageAccountName: storageAccount.name + diagnosticLogsRetentionInDays: contains(tableServices, 'diagnosticLogsRetentionInDays') ? tableServices.diagnosticLogsRetentionInDays : 365 + diagnosticStorageAccountId: contains(tableServices, 'diagnosticStorageAccountId') ? tableServices.diagnosticStorageAccountId : '' + diagnosticEventHubAuthorizationRuleId: contains(tableServices, 'diagnosticEventHubAuthorizationRuleId') ? tableServices.diagnosticEventHubAuthorizationRuleId : '' + diagnosticEventHubName: contains(tableServices, 'diagnosticEventHubName') ? tableServices.diagnosticEventHubName : '' + diagnosticLogCategoriesToEnable: contains(tableServices, 'diagnosticLogCategoriesToEnable') ? tableServices.diagnosticLogCategoriesToEnable : [] + diagnosticMetricsToEnable: contains(tableServices, 'diagnosticMetricsToEnable') ? tableServices.diagnosticMetricsToEnable : [] + tables: contains(tableServices, 'tables') ? tableServices.tables : [] + diagnosticWorkspaceId: contains(tableServices, 'diagnosticWorkspaceId') ? tableServices.diagnosticWorkspaceId : '' + enableDefaultTelemetry: enableDefaultTelemetry + } +} + +@description('The resource ID of the deployed storage account') +output resourceId string = storageAccount.id + +@description('The name of the deployed storage account') +output name string = storageAccount.name + +@description('The resource group of the deployed storage account') +output resourceGroupName string = resourceGroup().name + +@description('The primary blob endpoint reference if blob services are deployed.') +output primaryBlobEndpoint string = !empty(blobServices) && contains(blobServices, 'containers') ? reference('Microsoft.Storage/storageAccounts/${storageAccount.name}', '2019-04-01').primaryEndpoints.blob : '' + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(storageAccount.identity, 'principalId') ? storageAccount.identity.principalId : '' diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep new file mode 100644 index 000000000..7f1fea1b0 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/deploy.bicep @@ -0,0 +1,141 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the file service') +param name string = 'default' + +@description('Optional. Protocol settings for file service') +param protocolSettings object = {} + +@description('Optional. The service properties for soft delete.') +param shareDeleteRetentionPolicy object = { + enabled: true + days: 7 +} + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. File shares to create.') +param shares array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource fileServices 'Microsoft.Storage/storageAccounts/fileServices@2021-04-01' = { + name: name + parent: storageAccount + properties: { + protocolSettings: protocolSettings + shareDeleteRetentionPolicy: shareDeleteRetentionPolicy + } +} + +resource fileServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: fileServices +} + +module fileServices_shares 'shares/deploy.bicep' = [for (share, index) in shares: { + name: '${deployment().name}-shares-${index}' + params: { + storageAccountName: storageAccount.name + fileServicesName: fileServices.name + name: share.name + enabledProtocols: contains(share, 'enabledProtocols') ? share.enabledProtocols : 'SMB' + rootSquash: contains(share, 'rootSquash') ? share.rootSquash : 'NoRootSquash' + sharedQuota: contains(share, 'sharedQuota') ? share.sharedQuota : 5120 + roleAssignments: contains(share, 'roleAssignments') ? share.roleAssignments : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the deployed file share service') +output name string = fileServices.name + +@description('The resource ID of the deployed file share service') +output resourceId string = fileServices.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/readme.md new file mode 100644 index 000000000..00bfe0078 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/readme.md @@ -0,0 +1,59 @@ +# Storage Account file share services `[Microsoft.Storage/storageAccounts/fileServices]` + +This module can be used to deploy a file share service into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/fileServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the file service | +| `protocolSettings` | object | `{object}` | | Protocol settings for file service | +| `shareDeleteRetentionPolicy` | object | `{object}` | | The service properties for soft delete. | +| `shares` | _[shares](shares/readme.md)_ array | `[]` | | File shares to create. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Fileservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/fileServices) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts/fileServices/shares) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..8b32d3718 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/.bicep/nested_rbac.bicep @@ -0,0 +1,80 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Avere Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Blob Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + 'Storage Blob Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b') + 'Storage Blob Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') + 'Storage Blob Delegator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a') + 'Storage File Data SMB Share Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb') + 'Storage File Data SMB Share Elevated Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7') + 'Storage File Data SMB Share Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'Storage Table Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + 'Storage Table Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(fileShare.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: fileShare +}] diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep new file mode 100644 index 000000000..7e0fe99b8 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/deploy.bicep @@ -0,0 +1,83 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the file service') +param fileServicesName string = 'default' + +@description('Required. The name of the file share to create') +param name string + +@description('Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400.') +param sharedQuota int = 5120 + +@allowed([ + 'NFS' + 'SMB' +]) +@description('Optional. The authentication protocol that is used for the file share. Can only be specified when creating a share.') +param enabledProtocols string = 'SMB' + +@allowed([ + 'AllSquash' + 'NoRootSquash' + 'RootSquash' +]) +@description('Optional. Permissions for NFS file shares are enforced by the client OS rather than the Azure Files service. Toggling the root squash behavior reduces the rights of the root user for NFS shares.') +param rootSquash string = 'NoRootSquash' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource fileService 'fileServices@2021-04-01' existing = { + name: fileServicesName + } +} + +resource fileShare 'Microsoft.Storage/storageAccounts/fileServices/shares@2021-08-01' = { + name: name + parent: storageAccount::fileService + properties: { + shareQuota: sharedQuota + rootSquash: enabledProtocols == 'NFS' ? rootSquash : null + enabledProtocols: enabledProtocols + } +} + +module fileShare_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: fileShare.id + } +}] + +@description('The name of the deployed file share') +output name string = fileShare.name + +@description('The resource ID of the deployed file share') +output resourceId string = fileShare.id + +@description('The resource group of the deployed file share') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md new file mode 100644 index 000000000..51f132548 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/readme.md @@ -0,0 +1,75 @@ +# File Share `[Microsoft.Storage/storageAccounts/fileServices/shares]` + +This module deploys a storage account file share. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2021-08-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the file share to create | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enabledProtocols` | string | `'SMB'` | `[NFS, SMB]` | The authentication protocol that is used for the file share. Can only be specified when creating a share. | +| `fileServicesName` | string | `'default'` | | The name of the file service | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `rootSquash` | string | `'NoRootSquash'` | `[AllSquash, NoRootSquash, RootSquash]` | Permissions for NFS file shares are enforced by the client OS rather than the Azure Files service. Toggling the root squash behavior reduces the rights of the root user for NFS shares. | +| `sharedQuota` | int | `5120` | | The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share | +| `resourceGroupName` | string | The resource group of the deployed file share | +| `resourceId` | string | The resource ID of the deployed file share | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts/fileServices/shares) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/shares/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/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/fileServices/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/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep new file mode 100644 index 000000000..5d2c4dbe5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/deploy.bicep @@ -0,0 +1,48 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the storage container to deploy') +param name string = 'default' + +@description('Required. The Storage Account ManagementPolicies Rules') +param rules array + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +// lifecycle policy +resource managementPolicy 'Microsoft.Storage/storageAccounts/managementPolicies@2019-06-01' = if (!empty(rules)) { + name: name + parent: storageAccount + properties: { + policy: { + rules: rules + } + } +} + +@description('The resource ID of the deployed management policy') +output resourceId string = managementPolicy.name + +@description('The name of the deployed management policy') +output name string = managementPolicy.name + +@description('The resource group of the deployed management policy') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/readme.md new file mode 100644 index 000000000..499a6cf4e --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/readme.md @@ -0,0 +1,77 @@ +# Storage Account Management Policies `[Microsoft.Storage/storageAccounts/managementPolicies]` + +This module can be used to deploy a management policies into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/managementPolicies` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `rules` | array | The Storage Account ManagementPolicies Rules | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | The name of the storage container to deploy | + + +### Parameter Usage: `rules` + +```json +[ + { + "enabled": true, + "name": "retention-policy", + "type": "Lifecycle", + "definition": { + "actions": { + "baseBlob": { + "tierToArchive": { + "daysAfterModificationGreaterThan": 30 + }, + "delete": { + "daysAfterModificationGreaterThan": 1096 + } + }, + "snapshot": { + "delete": { + "daysAfterCreationGreaterThan": 1096 + } + } + }, + "filters": { + "blobTypes": [ + "blockBlob" + ] + } + } + } +] +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed management policy | +| `resourceGroupName` | string | The resource group of the deployed management policy | +| `resourceId` | string | The resource ID of the deployed management policy | + +## Template references + +- [Storageaccounts/Managementpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/managementPolicies) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/managementPolicies/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/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep new file mode 100644 index 000000000..a9f796e3b --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/deploy.bicep @@ -0,0 +1,127 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the queue service') +param name string = 'default' + +@description('Optional. Queues to create.') +param queues array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource queueServices 'Microsoft.Storage/storageAccounts/queueServices@2021-04-01' = { + name: name + parent: storageAccount + properties: {} +} + +resource queueServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: queueServices +} + +module queueServices_queues 'queues/deploy.bicep' = [for (queue, index) in queues: { + name: '${deployment().name}-Queue-${index}' + params: { + storageAccountName: storageAccount.name + queueServicesName: queueServices.name + name: queue.name + metadata: contains(queue, 'metadata') ? queue.metadata : {} + roleAssignments: contains(queue, 'roleAssignments') ? queue.roleAssignments : [] + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the deployed file share service') +output name string = queueServices.name + +@description('The resource ID of the deployed file share service') +output resourceId string = queueServices.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..c01e8ecce --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/.bicep/nested_rbac.bicep @@ -0,0 +1,77 @@ +@sys.description('Required. The IDs of the prinicpals to assign to role to') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. Description of role assignment') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Avere Cluster Create': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3') + 'Avere Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a') + 'Azure Service Deploy Release Management Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2') + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'CAL-Custom-Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 'Dsms Role (deprecated)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b') + 'Dsms Role (do not use)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f') + 'GenevaWarmPathResourceContributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Logic App Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'masterreader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Reader and Data Access': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'Site Recovery Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567') + 'Site Recovery Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca') + 'Storage Account Backup Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1') + 'Storage Account Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab') + 'Storage Account Key Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12') + 'Storage Queue Data Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + 'Storage Queue Data Message Processor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed') + 'Storage Queue Data Message Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a') + 'Storage Queue Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') +} + +resource queue 'Microsoft.Storage/storageAccounts/queueServices/queues@2019-06-01' existing = { + name: '${split(resourceId, '/')[8]}/${split(resourceId, '/')[10]}/${split(resourceId, '/')[12]}' +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(queue.name, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: queue +}] diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep new file mode 100644 index 000000000..20d60bedf --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/deploy.bicep @@ -0,0 +1,66 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the queue service') +param queueServicesName string = 'default' + +@description('Required. The name of the storage queue to deploy') +param name string + +@description('Required. A name-value pair that represents queue metadata.') +param metadata object = {} + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'') +param roleAssignments array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource queueServices 'queueServices@2021-06-01' existing = { + name: queueServicesName + } +} + +resource queue 'Microsoft.Storage/storageAccounts/queueServices/queues@2019-06-01' = { + name: name + parent: storageAccount::queueServices + properties: { + metadata: metadata + } +} + +module queue_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${deployment().name}-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: queue.id + } +}] + +@description('The name of the deployed queue') +output name string = queue.name + +@description('The resource ID of the deployed queue') +output resourceId string = queue.id + +@description('The resource group of the deployed queue') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md new file mode 100644 index 000000000..afbcaa568 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/readme.md @@ -0,0 +1,73 @@ +# Storage Account Queue `[Microsoft.Storage/storageAccounts/queueServices/queues]` + +This module deploys a storage account queue + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `metadata` | object | A name-value pair that represents queue metadata. | +| `name` | string | The name of the storage queue to deploy | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `queueServicesName` | string | `'default'` | The name of the queue service | +| `roleAssignments` | array | `[]` | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed queue | +| `resourceGroupName` | string | The resource group of the deployed queue | +| `resourceId` | string | The resource ID of the deployed queue | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/queues/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/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/readme.md new file mode 100644 index 000000000..45bfc3f04 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/readme.md @@ -0,0 +1,57 @@ +# Storage Account Queue Services `[Microsoft.Storage/storageAccounts/queueServices]` + +This module can be used to deploy a file share service into a storage account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/queueServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the queue service | +| `queues` | _[queues](queues/readme.md)_ array | `[]` | | Queues to create. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts/Queueservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/queueServices) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/queueServices/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/carml/1.2.0/Microsoft.Storage/storageAccounts/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/readme.md new file mode 100644 index 000000000..4738304f7 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/readme.md @@ -0,0 +1,224 @@ +# Storage Accounts `[Microsoft.Storage/storageAccounts]` + +This module is used to deploy a storage account, with the ability to deploy 1 or more blob containers, file shares, tables and queues. Optional ACLs can be configured on the storage account and optional RBAC can be assigned on the storage account and on each child resource. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Considerations](#Considerations) +- [Template references](#Template-references) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | +| `Microsoft.Storage/storageAccounts` | 2021-08-01 | +| `Microsoft.Storage/storageAccounts/blobServices` | 2021-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/fileServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/fileServices/shares` | 2021-08-01 | +| `Microsoft.Storage/storageAccounts/managementPolicies` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/queueServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/queueServices/queues` | 2019-06-01 | +| `Microsoft.Storage/storageAccounts/tableServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `allowBlobPublicAccess` | bool | `False` | | Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false. | +| `azureFilesIdentityBasedAuthentication` | object | `{object}` | | Provides the identity based authentication settings for Azure Files. | +| `blobServices` | _[blobServices](blobServices/readme.md)_ object | `{object}` | | Blob service and containers to deploy | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableHierarchicalNamespace` | bool | `False` | | If true, enables Hierarchical Namespace for the storage account | +| `fileServices` | _[fileServices](fileServices/readme.md)_ object | `{object}` | | File service and shares to deploy | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managementPolicyRules` | array | `[]` | | The Storage Account ManagementPolicies Rules. | +| `minimumTlsVersion` | string | `'TLS1_2'` | `[TLS1_0, TLS1_1, TLS1_2]` | Set the minimum TLS version on request to storage. | +| `name` | string | `''` | | Name of the Storage Account. Autogenerated with a unique string if not provided. | +| `networkAcls` | object | `{object}` | | Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny | +| `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible | +| `publicNetworkAccess` | string | `'Enabled'` | `[Enabled, Disabled]` | Enable or disallow public network access to Storage Account.. | +| `queueServices` | _[queueServices](queueServices/readme.md)_ object | `{object}` | | Queue service and queues to create. | +| `requireInfrastructureEncryption` | bool | `True` | | A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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' | +| `storageAccountAccessTier` | string | `'Hot'` | `[Hot, Cool]` | Storage Account Access Tier. | +| `storageAccountKind` | string | `'StorageV2'` | `[Storage, StorageV2, BlobStorage, FileStorage, BlockBlobStorage]` | Type of Storage Account to create. | +| `storageAccountSku` | string | `'Standard_GRS'` | `[Standard_LRS, Standard_GRS, Standard_RAGRS, Standard_ZRS, Premium_LRS, Premium_ZRS, Standard_GZRS, Standard_RAGZRS]` | Storage Account Sku Name. | +| `supportsHttpsTrafficOnly` | bool | `True` | | Allows HTTPS traffic only to storage service if sets to true. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tableServices` | _[tableServices](tableServices/readme.md)_ object | `{object}` | | Table service and tables to create. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `basetime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a SAS token to access the modules. | + + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `networkAcls` + +```json +"networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [ + { + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001" + } + ], + "ipRules": [ + { + "action": "Allow", + "value": "1.1.1.1" + } + ] + } +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "<>" // e.g. vault, registry, file, blob, queue, table etc. + } + ] +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed storage account | +| `primaryBlobEndpoint` | string | The primary blob endpoint reference if blob services are deployed. | +| `resourceGroupName` | string | The resource group of the deployed storage account | +| `resourceId` | string | The resource ID of the deployed storage account | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Considerations + +This is a generic module for deploying a Storage Account. Any customization for different storage needs (such as a diagnostic or other storage account) need to be done through the Archetype. +The hierarchical namespace of the storage account (see parameter `enableHierarchicalNamespace`), can be only set at creation time. + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Storageaccounts](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts) +- [Storageaccounts/Blobservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/blobServices) +- [Storageaccounts/Blobservices/Containers](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers) +- [Storageaccounts/Blobservices/Containers/Immutabilitypolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/blobServices/containers/immutabilityPolicies) +- [Storageaccounts/Fileservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/fileServices) +- [Storageaccounts/Fileservices/Shares](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-08-01/storageAccounts/fileServices/shares) +- [Storageaccounts/Managementpolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/managementPolicies) +- [Storageaccounts/Queueservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/queueServices) +- [Storageaccounts/Queueservices/Queues](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2019-06-01/storageAccounts/queueServices/queues) +- [Storageaccounts/Tableservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/tableServices) +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep new file mode 100644 index 000000000..580142ebf --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/deploy.bicep @@ -0,0 +1,125 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the table service') +param name string = 'default' + +@description('Optional. tables to create.') +param tables array = [] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of a log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +]) +param diagnosticLogCategoriesToEnable array = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'Transaction' +]) +param diagnosticMetricsToEnable array = [ + 'Transaction' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName +} + +resource tableServices 'Microsoft.Storage/storageAccounts/tableServices@2021-04-01' = { + name: name + parent: storageAccount + properties: {} +} + +resource tableServices_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: tableServices +} + +module tableServices_tables 'tables/deploy.bicep' = [for (tableName, index) in tables: { + name: '${deployment().name}-Table-${index}' + params: { + storageAccountName: storageAccount.name + tableServicesName: tableServices.name + name: tableName + enableDefaultTelemetry: enableDefaultTelemetry + } +}] + +@description('The name of the deployed table service') +output name string = tableServices.name + +@description('The resource ID of the deployed table service') +output resourceId string = tableServices.id + +@description('The resource group of the deployed table service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/readme.md new file mode 100644 index 000000000..399f3561e --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/readme.md @@ -0,0 +1,55 @@ +# Storage Account Table Services `[Microsoft.Storage/storageAccounts/tableServices]` + +This module deploys a storage account table service + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Storage/storageAccounts/tableServices` | 2021-04-01 | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogCategoriesToEnable` | array | `[StorageRead, StorageWrite, StorageDelete]` | `[StorageRead, StorageWrite, StorageDelete]` | The name of logs that will be streamed. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticMetricsToEnable` | array | `[Transaction]` | `[Transaction]` | The name of metrics that will be streamed. | +| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of a log analytics workspace. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `name` | string | `'default'` | | The name of the table service | +| `tables` | _[tables](tables/readme.md)_ array | `[]` | | tables to create. | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed table service | +| `resourceGroupName` | string | The resource group of the deployed table service | +| `resourceId` | string | The resource ID of the deployed table service | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Storageaccounts/Tableservices](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-04-01/storageAccounts/tableServices) +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep new file mode 100644 index 000000000..04a702ed5 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/deploy.bicep @@ -0,0 +1,46 @@ +@maxLength(24) +@description('Required. Name of the Storage Account.') +param storageAccountName string + +@description('Optional. The name of the table service') +param tableServicesName string = 'default' + +@description('Required. Name of the table.') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = { + name: storageAccountName + + resource tableServices 'tableServices@2021-04-01' existing = { + name: tableServicesName + } +} + +resource table 'Microsoft.Storage/storageAccounts/tableServices/tables@2021-06-01' = { + name: name + parent: storageAccount::tableServices +} + +@description('The name of the deployed file share service') +output name string = table.name + +@description('The resource ID of the deployed file share service') +output resourceId string = table.id + +@description('The resource group of the deployed file share service') +output resourceGroupName string = resourceGroup().name diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md new file mode 100644 index 000000000..cd164e271 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/readme.md @@ -0,0 +1,43 @@ +# Storage Account Table `[Microsoft.Storage/storageAccounts/tableServices/tables]` + +This module deploys a storage account table + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Template references](#Template-references) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Storage/storageAccounts/tableServices/tables` | 2021-06-01 | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the table. | +| `storageAccountName` | string | Name of the Storage Account. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `tableServicesName` | string | `'default'` | The name of the table service | + + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed file share service | +| `resourceGroupName` | string | The resource group of the deployed file share service | +| `resourceId` | string | The resource ID of the deployed file share service | + +## Template references + +- [Storageaccounts/Tableservices/Tables](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Storage/2021-06-01/storageAccounts/tableServices/tables) diff --git a/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/tables/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/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/tableServices/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/carml/1.2.0/Microsoft.Storage/storageAccounts/version.json b/carml/1.2.0/Microsoft.Storage/storageAccounts/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.Storage/storageAccounts/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/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep new file mode 100644 index 000000000..d8b3f95cd --- /dev/null +++ b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/.bicep/nested_rbac.bicep @@ -0,0 +1,53 @@ +@sys.description('Required. The IDs of the principals to assign the role to.') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to.') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. The description of the role assignment.') +param description string = '' + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2020-02-14' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = [for principalId in principalIds: { + name: guid(imageTemplate.id, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? principalType : null + } + scope: imageTemplate +}] diff --git a/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/.parameters/parameters.json b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/.parameters/parameters.json new file mode 100644 index 000000000..4b1b66c31 --- /dev/null +++ b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/.parameters/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": "<>-az-imgt-x-001" + }, + "userMsiName": { + "value": "adp-<>-az-msi-x-001" + }, + "userMsiResourceGroup": { + "value": "validation-rg" + }, + "buildTimeoutInMinutes": { + "value": 0 + }, + "vmSize": { + "value": "Standard_D2s_v3" + }, + "osDiskSizeGB": { + "value": 127 + }, + "subnetId": { + "value": "" + }, + "imageSource": { + "value": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-10", + "sku": "19h2-evd", + "version": "latest" + } + }, + "customizationSteps": { + "value": [ + { + "type": "WindowsRestart", + "restartTimeout": "30m" + } + ] + }, + "managedImageName": { + "value": "<>-az-mi-x-001" + }, + "unManagedImageName": { + "value": "<>-az-umi-x-001" + }, + "sigImageDefinitionId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/galleries/adp<>azsigweux001/images/adp-<>-az-imgd-x-001" + }, + "imageReplicationRegions": { + "value": [] + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + } + } +} diff --git a/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep new file mode 100644 index 000000000..a8cd98679 --- /dev/null +++ b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep @@ -0,0 +1,191 @@ +@description('Required. Name of the Image Template to be built by the Azure Image Builder service.') +param name string + +@description('Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder.') +param userMsiName string + +@description('Optional. Resource group of the user assigned identity.') +param userMsiResourceGroup string = resourceGroup().name + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes.') +@minValue(0) +@maxValue(960) +param buildTimeoutInMinutes int = 0 + +@description('Optional. Specifies the size for the VM.') +param vmSize string = 'Standard_D2s_v3' + +@description('Optional. Specifies the size of OS disk.') +param osDiskSizeGB int = 128 + +@description('Optional. Resource ID of an already existing subnet, e.g. \'/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/\'. If no value is provided, a new VNET will be created in the target Resource Group.') +param subnetId string = '' + +@description('Required. Image source definition in object format.') +param imageSource object + +@description('Required. Customization steps to be run when building the VM image.') +param customizationSteps array + +@description('Optional. Name of the managed image that will be created in the AIB resourcegroup.') +param managedImageName string = '' + +@description('Optional. Name of the unmanaged image that will be created in the AIB resourcegroup.') +param unManagedImageName string = '' + +@description('Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/.') +param sigImageDefinitionId string = '' + +@description('Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment\'s location will be taken as a default value.') +param imageReplicationRegions array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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\'.') +param roleAssignments array = [] + +var managedImageName_var = '${managedImageName}-${baseTime}' +var managedImageId = '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Compute/images/${managedImageName_var}' +var imageReplicationRegions_var = empty(imageReplicationRegions) ? array(location) : imageReplicationRegions + +var managedImage = { + type: 'ManagedImage' + imageId: managedImageId + location: location + runOutputName: '${managedImageName_var}-ManagedImage' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } +} +var conditionalManagedImage = empty(managedImageName) ? [] : array(managedImage) +var sharedImage = { + type: 'SharedImage' + galleryImageId: sigImageDefinitionId + runOutputName: !empty(sigImageDefinitionId) ? '${split(sigImageDefinitionId, '/')[10]}-SharedImage' : 'SharedImage' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } + replicationRegions: imageReplicationRegions_var +} +var conditionalSharedImage = empty(sigImageDefinitionId) ? [] : array(sharedImage) +var unManagedImage = { + type: 'VHD' + runOutputName: '${unManagedImageName}-VHD' + artifactTags: { + sourceType: imageSource.type + sourcePublisher: contains(imageSource, 'publisher') ? imageSource.publisher : null + sourceOffer: contains(imageSource, 'offer') ? imageSource.offer : null + sourceSku: contains(imageSource, 'sku') ? imageSource.sku : null + sourceVersion: contains(imageSource, 'version') ? imageSource.version : null + sourceImageId: contains(imageSource, 'imageId') ? imageSource.imageId : null + sourceImageVersionID: contains(imageSource, 'imageVersionID') ? imageSource.imageVersionID : null + creationTime: baseTime + } +} +var conditionalUnManagedImage = empty(unManagedImageName) ? [] : array(unManagedImage) +var distribute = concat(conditionalManagedImage, conditionalSharedImage, conditionalUnManagedImage) +var vnetConfig = { + subnetId: subnetId +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2020-02-14' = { + name: '${name}-${baseTime}' + location: location + tags: tags + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${az.resourceId(userMsiResourceGroup, 'Microsoft.ManagedIdentity/userAssignedIdentities', userMsiName)}': {} + } + } + properties: { + buildTimeoutInMinutes: buildTimeoutInMinutes + vmProfile: { + vmSize: vmSize + osDiskSizeGB: osDiskSizeGB + vnetConfig: !empty(subnetId) ? vnetConfig : null + } + source: imageSource + customize: customizationSteps + distribute: distribute + } +} + +resource imageTemplate_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${imageTemplate.name}-${lock}-lock' + properties: { + level: lock + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: imageTemplate +} + +module imageTemplate_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-ImageTemplate-Rbac-${index}' + params: { + description: contains(roleAssignment, 'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: imageTemplate.id + } +}] + +@description('The resource ID of the image template.') +output resourceId string = imageTemplate.id + +@description('The resource group the image template was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image template.') +output name string = imageTemplate.name + +@description('The command to run in order to trigger the image build.') +output runThisCommand string = 'Invoke-AzResourceAction -ResourceName ${imageTemplate.name} -ResourceGroupName ${resourceGroup().name} -ResourceType Microsoft.VirtualMachineImages/imageTemplates -Action Run -Force' + +@description('The location the resource was deployed into.') +output location string = imageTemplate.location diff --git a/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/readme.md b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/readme.md new file mode 100644 index 000000000..db014c980 --- /dev/null +++ b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/readme.md @@ -0,0 +1,138 @@ +# Image Templates `[Microsoft.VirtualMachineImages/imageTemplates]` + +This module deploys an image template that can be consumed by the Azure Image Builder (AIB) service. + +## Navigation + +- [Resource types](#Resource-types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) + +## Resource types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2017-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2020-10-01-preview](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-10-01-preview/roleAssignments) | +| `Microsoft.VirtualMachineImages/imageTemplates` | [2020-02-14](https://docs.microsoft.com/en-us/azure/templates/Microsoft.VirtualMachineImages/2020-02-14/imageTemplates) | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `customizationSteps` | array | Customization steps to be run when building the VM image. | +| `imageSource` | object | Image source definition in object format. | +| `name` | string | Name of the Image Template to be built by the Azure Image Builder service. | +| `userMsiName` | string | Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `buildTimeoutInMinutes` | int | `0` | | Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `imageReplicationRegions` | array | `[]` | | List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment's location will be taken as a default value. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `managedImageName` | string | `''` | | Name of the managed image that will be created in the AIB resourcegroup. | +| `osDiskSizeGB` | int | `128` | | Specifies the size of OS disk. | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'. | +| `sigImageDefinitionId` | string | `''` | | Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/. | +| `subnetId` | string | `''` | | Resource ID of an already existing subnet, e.g. '/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/'. If no value is provided, a new VNET will be created in the target Resource Group. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `unManagedImageName` | string | `''` | | Name of the unmanaged image that will be created in the AIB resourcegroup. | +| `userMsiResourceGroup` | string | `[resourceGroup().name]` | | Resource group of the user assigned identity. | +| `vmSize` | string | `'Standard_D2s_v3'` | | Specifies the size for the VM. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('yyyy-MM-dd-HH-mm-ss')]` | Do not provide a value! This date value is used to generate a unique image template name. | + + +### Parameter Usage: `imageSource` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +#### Platform Image + +```json +"source": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-10", + "sku": "19h2-evd", + "version": "latest" +} +``` + +#### Managed Image + +```json +"source": { + "type": "ManagedImage", + "imageId": "/subscriptions//resourceGroups/{destinationResourceGroupName}/providers/Microsoft.Compute/images/" +} +``` + +#### Shared Image + +```json +"source": { + "type": "SharedImageVersion", + "imageVersionID": "/subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/" +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the image template. | +| `resourceGroupName` | string | The resource group the image template was deployed into. | +| `resourceId` | string | The resource ID of the image template. | +| `runThisCommand` | string | The command to run in order to trigger the image build. | diff --git a/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/version.json b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/version.json new file mode 100644 index 000000000..56f8d9ca4 --- /dev/null +++ b/carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/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/carml/carmlVersionTracking.md b/carml/carmlVersionTracking.md new file mode 100644 index 000000000..93505294e --- /dev/null +++ b/carml/carmlVersionTracking.md @@ -0,0 +1,12 @@ +# CARML +# Module version tracking + +Mapping of AVD accelerator code and CARML module versions + +## Versions mapping + +CARML version | AVD accelerator version | Clone date | Delta | Tested +---|---|---|---|--- +0.4.0 | 1.0.0 | 03/03/2022 | - | yes +0.4.0 | 1.0.1 | 04/20/2022 | 120 commits ahead of 1.0.0 | no +0.5.0 | 1.2.0 | 05/13/2022 | - | yes \ No newline at end of file diff --git a/workload/arm/deploy-baseline.json b/workload/arm/deploy-baseline.json new file mode 100644 index 000000000..f13a8838d --- /dev/null +++ b/workload/arm/deploy-baseline.json @@ -0,0 +1,20810 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "13827207234965734546" + } + }, + "parameters": { + "deploymentPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. The name of the resource group to deploy" + }, + "maxLength": 4, + "minLength": 2 + }, + "avdSessionHostLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "avdManagementPlaneLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. Location where to deploy AVD management plane" + } + }, + "avdWorkloadSubsId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdEnterpriseAppObjectId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Azure Virtual Desktop Enterprise Application object ID. " + } + }, + "avdVmLocalUserName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. AVD session host local credentials" + } + }, + "avdVmLocalUserPassword": { + "type": "secureString", + "defaultValue": "" + }, + "avdIdentityDomainName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. AD domain name" + } + }, + "avdDomainJoinUserName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. AVD session host domain join credentials" + } + }, + "avdDomainJoinUserPassword": { + "type": "secureString", + "defaultValue": "" + }, + "avdOuPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. OU path to join AVd VMs" + } + }, + "avdHostPoolType": { + "type": "string", + "defaultValue": "Pooled", + "metadata": { + "description": "Optional. AVD host pool type (Default: Pooled)" + }, + "allowedValues": [ + "Personal", + "Pooled" + ] + }, + "avdPersonalAssignType": { + "type": "string", + "defaultValue": "Automatic", + "metadata": { + "description": "Optional. AVD host pool type (Default: Automatic)" + }, + "allowedValues": [ + "Automatic", + "Direct" + ] + }, + "avdHostPoolLoadBalancerType": { + "type": "string", + "defaultValue": "BreadthFirst", + "metadata": { + "description": "Required. AVD host pool load balacing type (Default: BreadthFirst)" + }, + "allowedValues": [ + "BreadthFirst", + "DepthFirst" + ] + }, + "avhHostPoolMaxSessions": { + "type": "int", + "defaultValue": 15, + "metadata": { + "description": "Optional. AVD host pool maximum number of user sessions per session host" + } + }, + "avdStartVmOnConnect": { + "type": "bool", + "metadata": { + "description": "Optional. AVD host pool start VM on Connect" + } + }, + "createStartVmOnConnectCustomRole": { + "type": "bool", + "metadata": { + "description": "Create custom Start VM on connect role" + } + }, + "avdDeployRappGroup": { + "type": "bool", + "metadata": { + "description": "Optional. AVD deploy remote app application group" + } + }, + "avdHostPoolRdpProperties": { + "type": "string", + "defaultValue": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2", + "metadata": { + "description": "Optional. AVD host pool Custom RDP properties" + } + }, + "createAvdVnet": { + "type": "bool", + "metadata": { + "description": "Create new virtual network" + } + }, + "existingVnetSubnetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Existing virtual network subnet" + } + }, + "existingHubVnetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Existing hub virtual network for perring" + } + }, + "avdVnetworkAddressPrefixes": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "AVD virtual network address prefixes" + } + }, + "avdVnetworkSubnetAddressPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "AVD virtual network subnet address prefix" + } + }, + "customDnsIps": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "custom DNS servers IPs" + } + }, + "avdVnetPrivateDnsZone": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Use Azure private DNS zones for private endpoints (Default: false)" + } + }, + "avdVnetPrivateDnsZoneFilesId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Use Azure private DNS zones for private endpoints (Default: false)" + } + }, + "avdVnetPrivateDnsZoneKeyvaultId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Use Azure private DNS zones for private endpoints (Default: false)" + } + }, + "vNetworkGatewayOnHub": { + "type": "bool", + "metadata": { + "description": "Does the hub contains a virtual network gateway" + } + }, + "avdFslogixFileShareQuotaSize": { + "type": "int", + "defaultValue": 512, + "metadata": { + "description": "Optional. Fslogix file share size (Default: 5TB)" + } + }, + "avdDeploySessionHosts": { + "type": "bool", + "metadata": { + "description": "Deploy new session hosts" + } + }, + "avdDeploySessionHostsCount": { + "type": "int", + "metadata": { + "description": "Cuantity of session hosts to deploy" + }, + "maxValue": 49, + "minValue": 1 + }, + "avdUseAvailabilityZones": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)" + } + }, + "avdAsFaultDomainCount": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "Optional. Sets the number of fault domains for the availability set. (Defualt: 3)" + } + }, + "avdAsUpdateDomainCount": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Optional. Sets the number of update domains for the availability set. (Defualt: 5)" + } + }, + "fsLogixStorageSku": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Storage account SKU for FSLogix storage. Recommended tier is Premium LRS or Premium ZRS (where available)" + } + }, + "encryptionAtHost": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "avdSessionHostsSize": { + "type": "string", + "defaultValue": "Standard_D2s_v3", + "metadata": { + "description": "Session host VM size (Defualt: Standard_D2s_v3) " + } + }, + "avdSessionHostDiskType": { + "type": "string", + "defaultValue": "Standard_LRS", + "metadata": { + "description": "OS disk type for session host (Defualt: Standard_LRS) " + } + }, + "avdOsImage": { + "type": "string", + "defaultValue": "win10_21h2", + "metadata": { + "description": "Required. AVD OS image source (Default: win10-21h2)" + }, + "allowedValues": [ + "win10_21h2_office", + "win10_21h2", + "win11_21h2_office", + "win11_21h2" + ] + }, + "useSharedImage": { + "type": "bool", + "metadata": { + "description": "Set to deploy image from Azure Compute Gallery" + } + }, + "avdImageTemplataDefinitionId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Source custom image ID" + } + }, + "storageOuName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "OU name for Azure Storage Account. It is recommended to create a new AD Organizational Unit (OU) in AD and disable password expiration policy on computer accounts or service logon accounts accordingly. " + } + }, + "createOuForStorage": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "If OU for Azure Storage needs to be created - set to true and ensure the domain join credentials have priviledge to create OU and create computer objects or join to domain" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "variables": { + "deploymentPrefixLowercase": "[toLower(parameters('deploymentPrefix'))]", + "avdSessionHostLocationLowercase": "[toLower(parameters('avdSessionHostLocation'))]", + "avdManagementPlaneLocationLowercase": "[toLower(parameters('avdManagementPlaneLocation'))]", + "avdServiceObjectsRgName": "[format('rg-{0}-avd-{1}-service-objects', variables('avdManagementPlaneLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdNetworkObjectsRgName": "[format('rg-{0}-avd-{1}-network', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdComputeObjectsRgName": "[format('rg-{0}-avd-{1}-pool-compute', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdStorageObjectsRgName": "[format('rg-{0}-avd-{1}-storage', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdSharedResourcesRgName": "[format('rg-{0}-avd-shared-resources', variables('avdSessionHostLocationLowercase'))]", + "avdVnetworkName": "[format('avdvnet-{0}-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdVnetworkSubnetName": "[format('avd-{0}', variables('deploymentPrefixLowercase'))]", + "avdNetworksecurityGroupName": "[format('avdnsg-{0}-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdRouteTableName": "[format('avdudr-{0}-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdApplicationsecurityGroupName": "[format('avdasg-{0}-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdVnetworkPeeringName": "[format('{0}-peering-avd-{1}', uniqueString(variables('deploymentPrefixLowercase'), parameters('avdSessionHostLocation')), variables('deploymentPrefixLowercase'))]", + "avdWorkSpaceName": "[format('avdws-{0}', variables('deploymentPrefixLowercase'))]", + "avdHostPoolName": "[format('avdhp-{0}', variables('deploymentPrefixLowercase'))]", + "avdApplicationGroupNameDesktop": "[format('avddag-{0}', variables('deploymentPrefixLowercase'))]", + "avdApplicationGroupNameRapp": "[format('avdraag-{0}', variables('deploymentPrefixLowercase'))]", + "marketPlaceGalleryWindows": { + "win10_21h2_office": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "office-365", + "sku": "win10-21h2-avd-m365", + "version": "latest" + }, + "win10_21h2": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "windows-10", + "sku": "win10-21h2-avd", + "version": "latest" + }, + "win11_21h2_office": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "office-365", + "sku": "win11-21h2-avd-m365", + "version": "latest" + }, + "win11_21h2": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-11", + "sku": "win11-21h2-avd", + "version": "latest" + } + }, + "baseScriptUri": "https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/", + "fslogixScriptUri": "[format('{0}scripts/Set-FSLogixRegKeys.ps1', variables('baseScriptUri'))]", + "fsLogixScript": "./Set-FSLogixRegKeys.ps1", + "fslogixSharePath": "[format('\\\\{0}.file.{1}\\{2}', variables('avdFslogixStorageName'), environment().suffixes.storage, variables('avdFslogixFileShareName'))]", + "FsLogixScriptArguments": "[format('-volumeshare {0}', variables('fslogixSharePath'))]", + "fslogixManagedIdentityName": "avd-uai-fslogix", + "avdAgentPackageLocation": "[format('https://wvdportalstorageblob.blob.{0}/galleryartifacts/Configuration_01-20-2022.zip', environment().suffixes.storage)]", + "avdFslogixStorageName": "[take(format('fslogix{0}{1}', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSessionHostLocationLowercase')), variables('deploymentPrefixLowercase')), 15)]", + "avdFslogixFileShareName": "[format('fslogix-{0}', variables('deploymentPrefixLowercase'))]", + "storageAccountContributorRoleId": "b24988ac-6180-42a0-ab88-20f7382dd24c", + "readerRoleId": "acdd72a7-3385-48ef-bd42-f606fba81ae7", + "tempStorageVmName": "tempstgvm", + "dscAgentPackageLocation": "https://github.com/Azure/avdaccelerator/raw/main/workload/scripts/DSCDomainJoinStorageScripts.zip", + "addStorageToDomainScriptUri": "[format('{0}scripts/Manual-DSC-JoinStorage-to-ADDS.ps1', variables('baseScriptUri'))]", + "addStorageToDomainScript": "./Manual-DSC-JoinStorage-to-ADDS.ps1", + "addStorageToDomainScriptArgs": "[format('-DscPath {0} -StorageAccountName {1} -StorageAccountRG {2} -DomainName {3} -AzureCloudEnvironment AzureCloud -DomainAdminUserName {4} -DomainAdminUserPassword {5} -OUName {6} -CreateNewOU {7} -ShareName {8} -Verbose', variables('dscAgentPackageLocation'), variables('avdFslogixStorageName'), variables('avdStorageObjectsRgName'), parameters('avdIdentityDomainName'), parameters('avdDomainJoinUserName'), parameters('avdDomainJoinUserPassword'), variables('OuStgName'), variables('createOuForStorageString'), variables('avdFslogixFileShareName'))]", + "OuStgName": "[if(not(empty(parameters('storageOuName'))), parameters('storageOuName'), 'Computers')]", + "avdWrklKvName": "[format('avd-{0}-{1}', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSessionHostLocationLowercase')), variables('deploymentPrefixLowercase'))]", + "avdSessionHostNamePrefix": "[format('avdsh-{0}', parameters('deploymentPrefix'))]", + "avdAvailabilitySetName": "[format('avdas-{0}', parameters('deploymentPrefix'))]", + "allAvailabilityZones": "[pickZones('Microsoft.Compute', 'virtualMachines', parameters('avdSessionHostLocation'), 3)]", + "createOuForStorageString": "[string(parameters('createOuForStorage'))]", + "resourceGroups": [ + { + "name": "[variables('avdServiceObjectsRgName')]", + "location": "[parameters('avdManagementPlaneLocation')]" + }, + { + "name": "[variables('avdComputeObjectsRgName')]", + "location": "[parameters('avdSessionHostLocation')]" + }, + { + "name": "[variables('avdStorageObjectsRgName')]", + "location": "[parameters('avdSessionHostLocation')]" + } + ] + }, + "resources": [ + { + "copy": { + "name": "avdBaselineResourceGroups", + "count": "[length(variables('resourceGroups'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-{0}-{1}', substring(variables('resourceGroups')[copyIndex()].name, 10), parameters('time'))]", + "subscriptionId": "[parameters('avdWorkloadSubsId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('resourceGroups')[copyIndex()].name]" + }, + "location": { + "value": "[variables('resourceGroups')[copyIndex()].location]" + }, + "enableDefaultTelemetry": { + "value": false + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16481433434056601602" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "location": "[parameters('location')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16502867888496328188" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3895574814240372849" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-Networking-{0}', parameters('time'))]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "avdApplicationsecurityGroupName": { + "value": "[variables('avdApplicationsecurityGroupName')]" + }, + "avdComputeObjectsRgName": { + "value": "[variables('avdComputeObjectsRgName')]" + }, + "avdNetworkObjectsRgName": { + "value": "[variables('avdNetworkObjectsRgName')]" + }, + "avdNetworksecurityGroupName": { + "value": "[variables('avdNetworksecurityGroupName')]" + }, + "avdRouteTableName": { + "value": "[variables('avdRouteTableName')]" + }, + "avdVnetworkAddressPrefixes": { + "value": "[parameters('avdVnetworkAddressPrefixes')]" + }, + "avdVnetworkName": { + "value": "[variables('avdVnetworkName')]" + }, + "avdVnetworkPeeringName": { + "value": "[variables('avdVnetworkPeeringName')]" + }, + "avdVnetworkSubnetName": { + "value": "[variables('avdVnetworkSubnetName')]" + }, + "createAvdVnet": { + "value": "[parameters('createAvdVnet')]" + }, + "vNetworkGatewayOnHub": { + "value": "[parameters('vNetworkGatewayOnHub')]" + }, + "existingHubVnetResourceId": { + "value": "[parameters('existingHubVnetResourceId')]" + }, + "avdSessionHostLocation": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "avdVnetworkSubnetAddressPrefix": { + "value": "[parameters('avdVnetworkSubnetAddressPrefix')]" + }, + "avdWorkloadSubsId": { + "value": "[parameters('avdWorkloadSubsId')]" + }, + "customDnsIps": { + "value": "[parameters('customDnsIps')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "575084739145673684" + } + }, + "parameters": { + "avdWorkloadSubsId": { + "type": "string", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdComputeObjectsRgName": { + "type": "string", + "metadata": { + "description": "Resource Group Name for the AVD session hosts" + } + }, + "createAvdVnet": { + "type": "bool", + "metadata": { + "description": "Create new virtual network" + } + }, + "avdNetworkObjectsRgName": { + "type": "string", + "metadata": { + "description": "Optional. If new virtual network required for the AVD machines. Resource Group name for the virtual network." + } + }, + "avdVnetworkName": { + "type": "string", + "metadata": { + "description": "Optional. Name of the virtual network if required to be created" + } + }, + "avdNetworksecurityGroupName": { + "type": "string", + "metadata": { + "description": "Network Security Group Name" + } + }, + "avdApplicationsecurityGroupName": { + "type": "string", + "metadata": { + "description": "Optional. Created if hte new VNet for AVD is created. Application Security Group (ASG) for the session hosts" + } + }, + "avdRouteTableName": { + "type": "string", + "metadata": { + "description": "Optional. Created if the new VNet for AVD is created. Route Table name." + } + }, + "vNetworkGatewayOnHub": { + "type": "bool", + "metadata": { + "description": "Does the hub contains a virtual network gateway" + } + }, + "existingHubVnetResourceId": { + "type": "string", + "metadata": { + "description": "Existing hub virtual network for perring" + } + }, + "avdVnetworkPeeringName": { + "type": "string", + "metadata": { + "description": "VNet peering name for AVD VNEt to vHub. " + } + }, + "avdVnetworkAddressPrefixes": { + "type": "string", + "metadata": { + "description": "AVD virtual network address prefixes" + } + }, + "avdVnetworkSubnetName": { + "type": "string", + "metadata": { + "description": "AVD subnet Name" + } + }, + "avdVnetworkSubnetAddressPrefix": { + "type": "string", + "metadata": { + "description": "AVD virtual network subnet address prefix" + } + }, + "customDnsIps": { + "type": "string", + "metadata": { + "description": "custom DNS servers IPs" + } + }, + "avdSessionHostLocation": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "resources": [ + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Network-{0}', parameters('time'))]", + "subscriptionId": "[parameters('avdWorkloadSubsId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdNetworkObjectsRgName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16481433434056601602" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "location": "[parameters('location')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16502867888496328188" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3895574814240372849" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-NSG-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdNetworkObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdNetworksecurityGroupName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17018305603501984264" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Network Security Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "securityRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the NSG resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "NetworkSecurityGroupEvent", + "NetworkSecurityGroupRuleCounter" + ], + "allowedValues": [ + "NetworkSecurityGroupEvent", + "NetworkSecurityGroupRuleCounter" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "securityRules", + "count": "[length(parameters('securityRules'))]", + "input": { + "name": "[parameters('securityRules')[copyIndex('securityRules')].name]", + "properties": { + "protocol": "[parameters('securityRules')[copyIndex('securityRules')].properties.protocol]", + "access": "[parameters('securityRules')[copyIndex('securityRules')].properties.access]", + "priority": "[parameters('securityRules')[copyIndex('securityRules')].properties.priority]", + "direction": "[parameters('securityRules')[copyIndex('securityRules')].properties.direction]", + "description": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'description'), parameters('securityRules')[copyIndex('securityRules')].properties.description, '')]", + "sourcePortRange": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'sourcePortRange'), parameters('securityRules')[copyIndex('securityRules')].properties.sourcePortRange, '')]", + "sourcePortRanges": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'sourcePortRanges'), parameters('securityRules')[copyIndex('securityRules')].properties.sourcePortRanges, createArray())]", + "destinationPortRange": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'destinationPortRange'), parameters('securityRules')[copyIndex('securityRules')].properties.destinationPortRange, '')]", + "destinationPortRanges": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'destinationPortRanges'), parameters('securityRules')[copyIndex('securityRules')].properties.destinationPortRanges, createArray())]", + "sourceAddressPrefix": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'sourceAddressPrefix'), parameters('securityRules')[copyIndex('securityRules')].properties.sourceAddressPrefix, '')]", + "destinationAddressPrefix": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'destinationAddressPrefix'), parameters('securityRules')[copyIndex('securityRules')].properties.destinationAddressPrefix, '')]", + "sourceAddressPrefixes": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'sourceAddressPrefixes'), parameters('securityRules')[copyIndex('securityRules')].properties.sourceAddressPrefixes, createArray())]", + "destinationAddressPrefixes": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'destinationAddressPrefixes'), parameters('securityRules')[copyIndex('securityRules')].properties.destinationAddressPrefixes, createArray())]", + "sourceApplicationSecurityGroups": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'sourceApplicationSecurityGroups'), parameters('securityRules')[copyIndex('securityRules')].properties.sourceApplicationSecurityGroups, createArray())]", + "destinationApplicationSecurityGroups": "[if(contains(parameters('securityRules')[copyIndex('securityRules')].properties, 'destinationApplicationSecurityGroups'), parameters('securityRules')[copyIndex('securityRules')].properties.destinationApplicationSecurityGroups, createArray())]" + } + } + } + ] + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "networkSecurityGroup_securityRules", + "count": "[length(parameters('securityRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-securityRule-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('securityRules')[copyIndex()].name]" + }, + "networkSecurityGroupName": { + "value": "[parameters('name')]" + }, + "protocol": { + "value": "[parameters('securityRules')[copyIndex()].properties.protocol]" + }, + "access": { + "value": "[parameters('securityRules')[copyIndex()].properties.access]" + }, + "priority": { + "value": "[parameters('securityRules')[copyIndex()].properties.priority]" + }, + "direction": { + "value": "[parameters('securityRules')[copyIndex()].properties.direction]" + }, + "description": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'description'), parameters('securityRules')[copyIndex()].properties.description, '')]" + }, + "sourcePortRange": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'sourcePortRange'), parameters('securityRules')[copyIndex()].properties.sourcePortRange, '')]" + }, + "sourcePortRanges": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'sourcePortRanges'), parameters('securityRules')[copyIndex()].properties.sourcePortRanges, createArray())]" + }, + "destinationPortRange": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'destinationPortRange'), parameters('securityRules')[copyIndex()].properties.destinationPortRange, '')]" + }, + "destinationPortRanges": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'destinationPortRanges'), parameters('securityRules')[copyIndex()].properties.destinationPortRanges, createArray())]" + }, + "sourceAddressPrefix": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'sourceAddressPrefix'), parameters('securityRules')[copyIndex()].properties.sourceAddressPrefix, '')]" + }, + "destinationAddressPrefix": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'destinationAddressPrefix'), parameters('securityRules')[copyIndex()].properties.destinationAddressPrefix, '')]" + }, + "sourceAddressPrefixes": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'sourceAddressPrefixes'), parameters('securityRules')[copyIndex()].properties.sourceAddressPrefixes, createArray())]" + }, + "destinationAddressPrefixes": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'destinationAddressPrefixes'), parameters('securityRules')[copyIndex()].properties.destinationAddressPrefixes, createArray())]" + }, + "sourceApplicationSecurityGroups": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'sourceApplicationSecurityGroups'), parameters('securityRules')[copyIndex()].properties.sourceApplicationSecurityGroups, createArray())]" + }, + "destinationApplicationSecurityGroups": { + "value": "[if(contains(parameters('securityRules')[copyIndex()].properties, 'destinationApplicationSecurityGroups'), parameters('securityRules')[copyIndex()].properties.destinationApplicationSecurityGroups, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1641174872808945709" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the security rule" + } + }, + "networkSecurityGroupName": { + "type": "string", + "metadata": { + "description": "Required. The name of the network security group to deploy the security rule into" + } + }, + "access": { + "type": "string", + "defaultValue": "Deny", + "allowedValues": [ + "Allow", + "Deny" + ], + "metadata": { + "description": "Optional. Whether network traffic is allowed or denied." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "maxLength": 140, + "metadata": { + "description": "Optional. A description for this rule" + } + }, + "destinationAddressPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The destination address prefix. CIDR or destination IP range. Asterisk \"*\" can also be used to match all source IPs. Default tags such as \"VirtualNetwork\", \"AzureLoadBalancer\" and \"Internet\" can also be used." + } + }, + "destinationAddressPrefixes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The destination address prefixes. CIDR or destination IP ranges." + } + }, + "destinationApplicationSecurityGroups": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The application security group specified as destination." + } + }, + "destinationPortRange": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The destination port or range. Integer or range between 0 and 65535. Asterisk \"*\" can also be used to match all ports." + } + }, + "destinationPortRanges": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The destination port ranges." + } + }, + "direction": { + "type": "string", + "allowedValues": [ + "Inbound", + "Outbound" + ], + "metadata": { + "description": "Required. The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic." + } + }, + "priority": { + "type": "int", + "metadata": { + "description": "Required. The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule." + } + }, + "protocol": { + "type": "string", + "allowedValues": [ + "*", + "Ah", + "Esp", + "Icmp", + "Tcp", + "Udp" + ], + "metadata": { + "description": "Required. Network protocol this rule applies to." + } + }, + "sourceAddressPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The CIDR or source IP range. Asterisk \"*\" can also be used to match all source IPs. Default tags such as \"VirtualNetwork\", \"AzureLoadBalancer\" and \"Internet\" can also be used. If this is an ingress rule, specifies where network traffic originates from." + } + }, + "sourceAddressPrefixes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The CIDR or source IP ranges." + } + }, + "sourceApplicationSecurityGroups": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The application security group specified as source." + } + }, + "sourcePortRange": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The source port or range. Integer or range between 0 and 65535. Asterisk \"*\" can also be used to match all ports." + } + }, + "sourcePortRanges": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The source port ranges." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/networkSecurityGroups/securityRules", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('networkSecurityGroupName'), parameters('name'))]", + "properties": { + "access": "[parameters('access')]", + "description": "[parameters('description')]", + "destinationAddressPrefix": "[parameters('destinationAddressPrefix')]", + "destinationAddressPrefixes": "[parameters('destinationAddressPrefixes')]", + "destinationApplicationSecurityGroups": "[parameters('destinationApplicationSecurityGroups')]", + "destinationPortRange": "[parameters('destinationPortRange')]", + "destinationPortRanges": "[parameters('destinationPortRanges')]", + "direction": "[parameters('direction')]", + "priority": "[parameters('priority')]", + "protocol": "[parameters('protocol')]", + "sourceAddressPrefix": "[parameters('sourceAddressPrefix')]", + "sourceAddressPrefixes": "[parameters('sourceAddressPrefixes')]", + "sourceApplicationSecurityGroups": "[parameters('sourceApplicationSecurityGroups')]", + "sourcePortRange": "[parameters('sourcePortRange')]", + "sourcePortRanges": "[parameters('sourcePortRanges')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the security rule was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/networkSecurityGroups/securityRules', parameters('networkSecurityGroupName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the security rule" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the security rule" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "networkSecurityGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-NSG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "13649518947101974639" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the network security group was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the network security group" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the network security group" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdWorkloadSubsId'), 'Microsoft.Resources/deployments', format('AVD-RG-Network-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-ASG-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdApplicationsecurityGroupName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "6018107131215671384" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application Security Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/applicationSecurityGroups", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/applicationSecurityGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "applicationSecurityGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppSecurityGroup-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "4848373449445594852" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "ExpressRoute Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/applicationSecurityGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the application security group was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the application security group" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the application security group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-UDR-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdNetworkObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdRouteTableName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15348737579919832076" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name given for the hub route table." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "routes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An Array of Routes to be established within the hub route table." + } + }, + "disableBgpRoutePropagation": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Switch to disable BGP route propagation." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/routeTables", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "routes": "[parameters('routes')]", + "disableBgpRoutePropagation": "[parameters('disableBgpRoutePropagation')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/routeTables/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/routeTables', parameters('name'))]" + ] + }, + { + "copy": { + "name": "routeTable_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RouteTable-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/routeTables', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1109718966019314469" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/routeTables/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/routeTables', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the route table was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the route table" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/routeTables', parameters('name'))]", + "metadata": { + "description": "The resource ID of the route table" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdWorkloadSubsId'), 'Microsoft.Resources/deployments', format('AVD-RG-Network-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-vNet-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdNetworkObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdVnetworkName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "addressPrefixes": { + "value": "[array(parameters('avdVnetworkAddressPrefixes'))]" + }, + "dnsServers": { + "value": "[if(not(empty(parameters('customDnsIps'))), array(parameters('customDnsIps')), createArray())]" + }, + "virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "[parameters('existingHubVnetResourceId')]", + "name": "[parameters('avdVnetworkPeeringName')]", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "doNotVerifyRemoteGateways": true, + "useRemoteGateways": "[if(parameters('vNetworkGatewayOnHub'), true(), false())]", + "remotePeeringEnabled": true, + "remotePeeringName": "[parameters('avdVnetworkPeeringName')]", + "remotePeeringAllowForwardedTraffic": true, + "remotePeeringAllowGatewayTransit": "[if(parameters('vNetworkGatewayOnHub'), true(), false())]", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringDoNotVerifyRemoteGateways": true, + "remotePeeringUseRemoteGateways": false + } + ] + }, + "subnets": { + "value": [ + { + "name": "[parameters('avdVnetworkSubnetName')]", + "addressPrefix": "[parameters('avdVnetworkSubnetAddressPrefix')]", + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled", + "networkSecurityGroupName": "[parameters('avdNetworksecurityGroupName')]", + "routeTableName": "[parameters('avdRouteTableName')]" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "13652506734939957315" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The Virtual Network (vNet) Name." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "addressPrefixes": { + "type": "array", + "metadata": { + "description": "Required. An Array of 1 or more IP Address Prefixes for the Virtual Network." + } + }, + "subnets": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An Array of subnets to deploy to the Virtual Network." + } + }, + "dnsServers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. DNS Servers associated to the Virtual Network." + } + }, + "ddosProtectionPlanId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the DDoS protection plan to assign the VNET to. If it's left blank, DDoS protection will not be configured. If it's provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription." + } + }, + "virtualNetworkPeerings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Virtual Network Peerings configurations" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "VMProtectionAlerts" + ], + "allowedValues": [ + "VMProtectionAlerts" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "dnsServers_var": { + "dnsServers": "[array(parameters('dnsServers'))]" + }, + "ddosProtectionPlan": { + "id": "[parameters('ddosProtectionPlanId')]" + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "subnets", + "count": "[length(parameters('subnets'))]", + "input": { + "name": "[parameters('subnets')[copyIndex('subnets')].name]", + "properties": { + "addressPrefix": "[parameters('subnets')[copyIndex('subnets')].addressPrefix]", + "addressPrefixes": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'addressPrefixes'), parameters('subnets')[copyIndex('subnets')].addressPrefixes, createArray())]", + "applicationGatewayIpConfigurations": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'applicationGatewayIpConfigurations'), parameters('subnets')[copyIndex('subnets')].applicationGatewayIpConfigurations, createArray())]", + "delegations": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'delegations'), parameters('subnets')[copyIndex('subnets')].delegations, createArray())]", + "ipAllocations": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'ipAllocations'), parameters('subnets')[copyIndex('subnets')].ipAllocations, createArray())]", + "natGateway": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'natGatewayId'), createObject('id', parameters('subnets')[copyIndex('subnets')].natGatewayId), json('null'))]", + "networkSecurityGroup": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'networkSecurityGroupId'), createObject('id', parameters('subnets')[copyIndex('subnets')].networkSecurityGroupId), json('null'))]", + "privateEndpointNetworkPolicies": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'privateEndpointNetworkPolicies'), parameters('subnets')[copyIndex('subnets')].privateEndpointNetworkPolicies, null())]", + "privateLinkServiceNetworkPolicies": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'privateLinkServiceNetworkPolicies'), parameters('subnets')[copyIndex('subnets')].privateLinkServiceNetworkPolicies, null())]", + "routeTable": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'routeTableId'), createObject('id', parameters('subnets')[copyIndex('subnets')].routeTableId), json('null'))]", + "serviceEndpoints": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'serviceEndpoints'), parameters('subnets')[copyIndex('subnets')].serviceEndpoints, createArray())]", + "serviceEndpointPolicies": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'serviceEndpointPolicies'), parameters('subnets')[copyIndex('subnets')].serviceEndpointPolicies, createArray())]" + } + } + } + ], + "addressSpace": { + "addressPrefixes": "[parameters('addressPrefixes')]" + }, + "ddosProtectionPlan": "[if(not(empty(parameters('ddosProtectionPlanId'))), variables('ddosProtectionPlan'), null())]", + "dhcpOptions": "[if(not(empty(parameters('dnsServers'))), variables('dnsServers_var'), null())]", + "enableDdosProtection": "[not(empty(parameters('ddosProtectionPlanId')))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "copy": { + "name": "virtualNetwork_subnets", + "count": "[length(parameters('subnets'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-subnet-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualNetworkName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('subnets')[copyIndex()].name]" + }, + "addressPrefix": { + "value": "[parameters('subnets')[copyIndex()].addressPrefix]" + }, + "addressPrefixes": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'addressPrefixes'), parameters('subnets')[copyIndex()].addressPrefixes, createArray())]" + }, + "applicationGatewayIpConfigurations": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'applicationGatewayIpConfigurations'), parameters('subnets')[copyIndex()].applicationGatewayIpConfigurations, createArray())]" + }, + "delegations": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'delegations'), parameters('subnets')[copyIndex()].delegations, createArray())]" + }, + "ipAllocations": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'ipAllocations'), parameters('subnets')[copyIndex()].ipAllocations, createArray())]" + }, + "natGatewayId": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'natGatewayId'), parameters('subnets')[copyIndex()].natGatewayId, '')]" + }, + "networkSecurityGroupId": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'networkSecurityGroupId'), parameters('subnets')[copyIndex()].networkSecurityGroupId, '')]" + }, + "privateEndpointNetworkPolicies": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'privateEndpointNetworkPolicies'), parameters('subnets')[copyIndex()].privateEndpointNetworkPolicies, '')]" + }, + "privateLinkServiceNetworkPolicies": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'privateLinkServiceNetworkPolicies'), parameters('subnets')[copyIndex()].privateLinkServiceNetworkPolicies, '')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'roleAssignments'), parameters('subnets')[copyIndex()].roleAssignments, createArray())]" + }, + "routeTableId": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'routeTableId'), parameters('subnets')[copyIndex()].routeTableId, '')]" + }, + "serviceEndpointPolicies": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'serviceEndpointPolicies'), parameters('subnets')[copyIndex()].serviceEndpointPolicies, createArray())]" + }, + "serviceEndpoints": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'serviceEndpoints'), parameters('subnets')[copyIndex()].serviceEndpoints, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17892816726991291054" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Optional. The Name of the subnet resource." + } + }, + "virtualNetworkName": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent virtual network" + } + }, + "addressPrefix": { + "type": "string", + "metadata": { + "description": "Required. The address prefix for the subnet." + } + }, + "networkSecurityGroupId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of the network security group to assign to the subnet" + } + }, + "routeTableId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of the route table to assign to the subnet" + } + }, + "serviceEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The service endpoints to enable on the subnet" + } + }, + "delegations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The delegations to enable on the subnet" + } + }, + "natGatewayId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of the NAT Gateway to use for the subnet" + } + }, + "privateEndpointNetworkPolicies": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Disabled", + "Enabled", + "" + ], + "metadata": { + "description": "Optional. enable or disable apply network policies on private endpoint in the subnet." + } + }, + "privateLinkServiceNetworkPolicies": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Disabled", + "Enabled", + "" + ], + "metadata": { + "description": "Optional. enable or disable apply network policies on private link service in the subnet." + } + }, + "addressPrefixes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of address prefixes for the subnet." + } + }, + "applicationGatewayIpConfigurations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Application gateway IP configurations of virtual network resource." + } + }, + "ipAllocations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of IpAllocation which reference this subnet" + } + }, + "serviceEndpointPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of service endpoint policies." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('virtualNetworkName'), parameters('name'))]", + "properties": { + "addressPrefix": "[parameters('addressPrefix')]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupId'))), createObject('id', parameters('networkSecurityGroupId')), null())]", + "routeTable": "[if(not(empty(parameters('routeTableId'))), createObject('id', parameters('routeTableId')), null())]", + "natGateway": "[if(not(empty(parameters('natGatewayId'))), createObject('id', parameters('natGatewayId')), null())]", + "serviceEndpoints": "[parameters('serviceEndpoints')]", + "delegations": "[parameters('delegations')]", + "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", + "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "addressPrefixes": "[parameters('addressPrefixes')]", + "applicationGatewayIpConfigurations": "[parameters('applicationGatewayIpConfigurations')]", + "ipAllocations": "[parameters('ipAllocations')]", + "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]" + } + }, + { + "copy": { + "name": "subnet_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Subnet-Rbac-{1}', uniqueString(deployment().name, resourceGroup().location), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2860979149048842211" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}/subnets/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network peering was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network peering" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network peering" + } + }, + "subnetAddressPrefix": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))).addressPrefix]", + "metadata": { + "description": "The address prefix for the subnet" + } + }, + "subnetAddressPrefixes": { + "type": "array", + "value": "[if(not(empty(parameters('addressPrefixes'))), reference(resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))).addressPrefixes, createArray())]", + "metadata": { + "description": "List of address prefixes for the subnet" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "copy": { + "name": "virtualNetwork_peering_local", + "count": "[length(parameters('virtualNetworkPeerings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-virtualNetworkPeering-local-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "localVnetName": { + "value": "[parameters('name')]" + }, + "remoteVirtualNetworkId": { + "value": "[parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId]" + }, + "name": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'name'), parameters('virtualNetworkPeerings')[copyIndex()].name, format('{0}-{1}', parameters('name'), last(split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/'))))]" + }, + "allowForwardedTraffic": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'allowForwardedTraffic'), parameters('virtualNetworkPeerings')[copyIndex()].allowForwardedTraffic, true())]" + }, + "allowGatewayTransit": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'allowGatewayTransit'), parameters('virtualNetworkPeerings')[copyIndex()].allowGatewayTransit, false())]" + }, + "allowVirtualNetworkAccess": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'allowVirtualNetworkAccess'), parameters('virtualNetworkPeerings')[copyIndex()].allowVirtualNetworkAccess, true())]" + }, + "doNotVerifyRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'doNotVerifyRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].doNotVerifyRemoteGateways, true())]" + }, + "useRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'useRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].useRemoteGateways, false())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7559102270543126453" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]", + "metadata": { + "description": "Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName" + } + }, + "localVnetName": { + "type": "string", + "metadata": { + "description": "Required. The Name of the Virtual Network to add the peering to." + } + }, + "remoteVirtualNetworkId": { + "type": "string", + "metadata": { + "description": "Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID" + } + }, + "allowForwardedTraffic": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true" + } + }, + "allowGatewayTransit": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false" + } + }, + "allowVirtualNetworkAccess": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true" + } + }, + "doNotVerifyRemoteGateways": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If we need to verify the provisioning state of the remote gateway. Default is true" + } + }, + "useRemoteGateways": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('localVnetName'), parameters('name'))]", + "properties": { + "allowForwardedTraffic": "[parameters('allowForwardedTraffic')]", + "allowGatewayTransit": "[parameters('allowGatewayTransit')]", + "allowVirtualNetworkAccess": "[parameters('allowVirtualNetworkAccess')]", + "doNotVerifyRemoteGateways": "[parameters('doNotVerifyRemoteGateways')]", + "useRemoteGateways": "[parameters('useRemoteGateways')]", + "remoteVirtualNetwork": { + "id": "[parameters('remoteVirtualNetworkId')]" + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network peering was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network peering" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/virtualNetworkPeerings', parameters('localVnetName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network peering" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "condition": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringEnabled'), equals(parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringEnabled, true()), false())]", + "copy": { + "name": "virtualNetwork_peering_remote", + "count": "[length(parameters('virtualNetworkPeerings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-virtualNetworkPeering-remote-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "subscriptionId": "[split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/')[2]]", + "resourceGroup": "[split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/')[4]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "localVnetName": { + "value": "[last(split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/'))]" + }, + "remoteVirtualNetworkId": { + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + }, + "name": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringName'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringName, format('{0}-{1}', last(split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/')), parameters('name')))]" + }, + "allowForwardedTraffic": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringAllowForwardedTraffic'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringAllowForwardedTraffic, true())]" + }, + "allowGatewayTransit": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringAllowGatewayTransit'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringAllowGatewayTransit, false())]" + }, + "allowVirtualNetworkAccess": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringAllowVirtualNetworkAccess'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringAllowVirtualNetworkAccess, true())]" + }, + "doNotVerifyRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringDoNotVerifyRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringDoNotVerifyRemoteGateways, true())]" + }, + "useRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringUseRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringUseRemoteGateways, false())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7559102270543126453" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]", + "metadata": { + "description": "Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName" + } + }, + "localVnetName": { + "type": "string", + "metadata": { + "description": "Required. The Name of the Virtual Network to add the peering to." + } + }, + "remoteVirtualNetworkId": { + "type": "string", + "metadata": { + "description": "Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID" + } + }, + "allowForwardedTraffic": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true" + } + }, + "allowGatewayTransit": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false" + } + }, + "allowVirtualNetworkAccess": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true" + } + }, + "doNotVerifyRemoteGateways": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If we need to verify the provisioning state of the remote gateway. Default is true" + } + }, + "useRemoteGateways": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('localVnetName'), parameters('name'))]", + "properties": { + "allowForwardedTraffic": "[parameters('allowForwardedTraffic')]", + "allowGatewayTransit": "[parameters('allowGatewayTransit')]", + "allowVirtualNetworkAccess": "[parameters('allowVirtualNetworkAccess')]", + "doNotVerifyRemoteGateways": "[parameters('doNotVerifyRemoteGateways')]", + "useRemoteGateways": "[parameters('useRemoteGateways')]", + "remoteVirtualNetwork": { + "id": "[parameters('remoteVirtualNetworkId')]" + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network peering was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network peering" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/virtualNetworkPeerings', parameters('localVnetName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network peering" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "copy": { + "name": "virtualNetwork_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VNet-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3080904817612260359" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network" + } + }, + "subnetNames": { + "type": "array", + "copy": { + "count": "[length(parameters('subnets'))]", + "input": "[parameters('subnets')[copyIndex()].name]" + }, + "metadata": { + "description": "The names of the deployed subnets" + } + }, + "subnetResourceIds": { + "type": "array", + "copy": { + "count": "[length(parameters('subnets'))]", + "input": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('name'), parameters('subnets')[copyIndex()].name)]" + }, + "metadata": { + "description": "The resource IDs of the deployed subnets" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-ASG-{0}', parameters('time')))]", + "[subscriptionResourceId(parameters('avdWorkloadSubsId'), 'Microsoft.Resources/deployments', format('AVD-RG-Network-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-NSG-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-UDR-{0}', parameters('time')))]" + ] + } + ], + "outputs": { + "avdApplicationSecurityGroupResourceId": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-ASG-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value]" + }, + "avdVirtualNetworkResourceId": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value]" + } + } + } + }, + "dependsOn": [ + "avdBaselineResourceGroups" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-HostPool-AppGroups-{0}', parameters('time'))]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "avdApplicationGroupNameDesktop": { + "value": "[variables('avdApplicationGroupNameDesktop')]" + }, + "avdApplicationGroupNameRapp": { + "value": "[variables('avdApplicationGroupNameRapp')]" + }, + "avdDeployRappGroup": { + "value": "[parameters('avdDeployRappGroup')]" + }, + "avdHostPoolName": { + "value": "[variables('avdHostPoolName')]" + }, + "avdHostPoolRdpProperties": { + "value": "[parameters('avdHostPoolRdpProperties')]" + }, + "avdHostPoolLoadBalancerType": { + "value": "[parameters('avdHostPoolLoadBalancerType')]" + }, + "avdHostPoolType": { + "value": "[parameters('avdHostPoolType')]" + }, + "avhHostPoolMaxSessions": { + "value": "[parameters('avhHostPoolMaxSessions')]" + }, + "avdPersonalAssignType": { + "value": "[parameters('avdPersonalAssignType')]" + }, + "avdManagementPlaneLocation": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "avdServiceObjectsRgName": { + "value": "[variables('avdServiceObjectsRgName')]" + }, + "avdStartVmOnConnect": { + "value": "[parameters('avdStartVmOnConnect')]" + }, + "avdWorkloadSubsId": { + "value": "[parameters('avdWorkloadSubsId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8613039019663993477" + } + }, + "parameters": { + "avdManagementPlaneLocation": { + "type": "string", + "metadata": { + "description": "Required. Location where to deploy AVD management plane" + } + }, + "avdWorkloadSubsId": { + "type": "string", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdServiceObjectsRgName": { + "type": "string", + "metadata": { + "description": "AVD Resource Group Name for the service objects" + } + }, + "avdApplicationGroupNameRapp": { + "type": "string", + "metadata": { + "description": "Optional. AVD Application Group Name for the applications." + } + }, + "avdApplicationGroupNameDesktop": { + "type": "string", + "metadata": { + "description": "AVD Application group for the session hosts. Desktop type." + } + }, + "avdDeployRappGroup": { + "type": "bool", + "metadata": { + "description": "Optional. AVD deploy remote app application group" + } + }, + "avdHostPoolName": { + "type": "string", + "metadata": { + "description": "AVD Host Pool Name" + } + }, + "avdHostPoolRdpProperties": { + "type": "string", + "metadata": { + "description": "Optional. AVD host pool Custom RDP properties" + } + }, + "avdHostPoolType": { + "type": "string", + "metadata": { + "description": "Optional. AVD host pool type (Default: Pooled)" + }, + "allowedValues": [ + "Personal", + "Pooled" + ] + }, + "avdPersonalAssignType": { + "type": "string", + "metadata": { + "description": "Optional. AVD host pool type (Default: Automatic)" + }, + "allowedValues": [ + "Automatic", + "Direct" + ] + }, + "avdHostPoolLoadBalancerType": { + "type": "string", + "metadata": { + "description": "Required. AVD host pool load balacing type (Default: BreadthFirst)" + }, + "allowedValues": [ + "BreadthFirst", + "DepthFirst" + ] + }, + "avhHostPoolMaxSessions": { + "type": "int", + "metadata": { + "description": "Optional. AVD host pool maximum number of user sessions per session host" + } + }, + "avdStartVmOnConnect": { + "type": "bool", + "metadata": { + "description": "Optional. AVD host pool start VM on Connect" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "variables": { + "desktopApplicaitonGroups": [ + { + "name": "[parameters('avdApplicationGroupNameDesktop')]", + "location": "[parameters('avdManagementPlaneLocation')]", + "applicationGroupType": "Desktop" + } + ], + "applicationApplicationGroups": [ + { + "name": "[parameters('avdApplicationGroupNameRapp')]", + "location": "[parameters('avdManagementPlaneLocation')]", + "applicationGroupType": "RemoteApp" + } + ], + "finalApplicationGroups": "[if(parameters('avdDeployRappGroup'), concat(variables('desktopApplicaitonGroups'), variables('applicationApplicationGroups')), variables('desktopApplicaitonGroups'))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-HostPool-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdHostPoolName')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "hostpoolType": { + "value": "[parameters('avdHostPoolType')]" + }, + "startVMOnConnect": { + "value": "[parameters('avdStartVmOnConnect')]" + }, + "customRdpProperty": { + "value": "[parameters('avdHostPoolRdpProperties')]" + }, + "loadBalancerType": { + "value": "[parameters('avdHostPoolLoadBalancerType')]" + }, + "maxSessionLimit": { + "value": "[parameters('avhHostPoolMaxSessions')]" + }, + "personalDesktopAssignmentType": { + "value": "[parameters('avdPersonalAssignType')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "4342317450154168179" + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Host Pool" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "hostpoolFriendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Host Pool to be created." + } + }, + "hostpoolDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Host Pool to be created." + } + }, + "hostpoolType": { + "type": "string", + "defaultValue": "Pooled", + "allowedValues": [ + "Personal", + "Pooled" + ], + "metadata": { + "description": "Optional. Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled." + } + }, + "personalDesktopAssignmentType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Automatic", + "Direct", + "" + ], + "metadata": { + "description": "Optional. Set the type of assignment for a Personal Host Pool type" + } + }, + "loadBalancerType": { + "type": "string", + "defaultValue": "BreadthFirst", + "allowedValues": [ + "BreadthFirst", + "DepthFirst", + "Persistent" + ], + "metadata": { + "description": "Optional. Type of load balancer algorithm." + } + }, + "maxSessionLimit": { + "type": "int", + "defaultValue": 99999, + "metadata": { + "description": "Optional. Maximum number of sessions." + } + }, + "customRdpProperty": { + "type": "string", + "defaultValue": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;", + "metadata": { + "description": "Optional. Host Pool RDP properties" + } + }, + "validationEnviroment": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation 'ring' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment." + } + }, + "vmTemplate": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The necessary information for adding more VMs to this Host Pool." + } + }, + "tokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. Host Pool token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the token will be valid for 8 hours." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "preferredAppGroupType": { + "type": "string", + "defaultValue": "Desktop", + "allowedValues": [ + "Desktop", + "None", + "RailApplications" + ], + "metadata": { + "description": "Optional. The type of preferred application group type, default to Desktop Application Group" + } + }, + "startVMOnConnect": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs." + } + }, + "validationEnvironment": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Validation host pool allows you to test service changes before they are deployed to production." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management", + "Connection", + "HostRegistration", + "AgentHealthStatus" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management", + "Connection", + "HostRegistration", + "AgentHealthStatus" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "tokenExpirationTime": "[dateTimeAdd(parameters('baseTime'), parameters('tokenValidityLength'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DesktopVirtualization/hostPools", + "apiVersion": "2021-07-12", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "friendlyName": "[parameters('hostpoolFriendlyName')]", + "description": "[parameters('hostpoolDescription')]", + "hostPoolType": "[parameters('hostpoolType')]", + "customRdpProperty": "[parameters('customRdpProperty')]", + "personalDesktopAssignmentType": "[parameters('personalDesktopAssignmentType')]", + "preferredAppGroupType": "[parameters('preferredAppGroupType')]", + "maxSessionLimit": "[parameters('maxSessionLimit')]", + "loadBalancerType": "[parameters('loadBalancerType')]", + "validationEnviroment": "[parameters('validationEnviroment')]", + "startVMOnConnect": "[parameters('startVMOnConnect')]", + "validationEnvironment": "[parameters('validationEnvironment')]", + "registrationInfo": { + "expirationTime": "[variables('tokenExpirationTime')]", + "token": null, + "registrationTokenOperation": "Update" + }, + "vmTemplate": "[if(not(empty(parameters('vmTemplate'))), null(), string(parameters('vmTemplate')))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/hostPools/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/hostPools/{0}', parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + ] + }, + { + "copy": { + "name": "hostPool_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-HostPool-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "5218447485299245803" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8')]", + "Desktop Virtualization Application Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Host Pool Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc')]", + "Desktop Virtualization Host Pool Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization Session Host Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408')]", + "Desktop Virtualization User Session Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/hostPools/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD host pool" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD host pool was deployed into" + } + }, + "hostPoolRestrationInfo": { + "type": "object", + "value": "[reference(resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))).registrationInfo]" + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD host pool" + } + }, + "tokenExpirationTime": { + "type": "string", + "value": "[dateTimeAdd(parameters('baseTime'), parameters('tokenValidityLength'))]", + "metadata": { + "description": "The expiration time for the registration token" + } + } + } + } + } + }, + { + "copy": { + "name": "avdApplicationGroups", + "count": "[length(variables('finalApplicationGroups'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AppGroup-{0}-{1}', variables('finalApplicationGroups')[copyIndex()].name, parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('finalApplicationGroups')[copyIndex()].name]" + }, + "location": { + "value": "[variables('finalApplicationGroups')[copyIndex()].location]" + }, + "applicationGroupType": { + "value": "[variables('finalApplicationGroups')[copyIndex()].applicationGroupType]" + }, + "hostpoolName": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))).outputs.name.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7082591156001948892" + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Application Group to create this application in." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "applicationGroupType": { + "type": "string", + "allowedValues": [ + "RemoteApp", + "Desktop" + ], + "metadata": { + "description": "Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop" + } + }, + "hostpoolName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Host Pool to be linked to this Application Group." + } + }, + "friendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Application Group to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Application Group to be created." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of log analytics." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "applications": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of applications to be created in the Application Group." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DesktopVirtualization/applicationGroups", + "apiVersion": "2021-07-12", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "hostPoolArmPath": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('hostpoolName'))]", + "friendlyName": "[parameters('friendlyName')]", + "description": "[parameters('description')]", + "applicationGroupType": "[parameters('applicationGroupType')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "appGroup_applications", + "count": "[length(parameters('applications'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppGroup-App-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('applications')[copyIndex()].name]" + }, + "appGroupName": { + "value": "[parameters('name')]" + }, + "description": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'description'), parameters('applications')[copyIndex()].description, '')]" + }, + "friendlyName": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'friendlyName'), parameters('applications')[copyIndex()].friendlyName, parameters('name'))]" + }, + "filePath": { + "value": "[parameters('applications')[copyIndex()].filePath]" + }, + "commandLineSetting": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'commandLineSetting'), parameters('applications')[copyIndex()].commandLineSetting, 'DoNotAllow')]" + }, + "commandLineArguments": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'commandLineArguments'), parameters('applications')[copyIndex()].commandLineArguments, '')]" + }, + "showInPortal": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'showInPortal'), parameters('applications')[copyIndex()].showInPortal, false())]" + }, + "iconPath": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'iconPath'), parameters('applications')[copyIndex()].iconPath, parameters('applications')[copyIndex()].filePath)]" + }, + "iconIndex": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'iconIndex'), parameters('applications')[copyIndex()].iconIndex, 0)]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "10183668216278260214" + } + }, + "parameters": { + "appGroupName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application Group to create the application(s) in." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application to be created in the Application Group." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of Application.." + } + }, + "friendlyName": { + "type": "string", + "metadata": { + "description": "Required. Friendly name of Application.." + } + }, + "filePath": { + "type": "string", + "metadata": { + "description": "Required. Specifies a path for the executable file for the application." + } + }, + "commandLineSetting": { + "type": "string", + "defaultValue": "DoNotAllow", + "metadata": { + "description": "Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all." + }, + "allowedValues": [ + "Allow", + "DoNotAllow", + "Require" + ] + }, + "commandLineArguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-Line Arguments for Application." + } + }, + "showInPortal": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether to show the RemoteApp program in the RD Web Access server." + } + }, + "iconPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Path to icon." + } + }, + "iconIndex": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Index of the icon." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DesktopVirtualization/applicationGroups/applications", + "apiVersion": "2021-07-12", + "name": "[format('{0}/{1}', parameters('appGroupName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "friendlyName": "[parameters('friendlyName')]", + "filePath": "[parameters('filePath')]", + "commandLineSetting": "[parameters('commandLineSetting')]", + "commandLineArguments": "[parameters('commandLineArguments')]", + "showInPortal": "[parameters('showInPortal')]", + "iconPath": "[parameters('iconPath')]", + "iconIndex": "[parameters('iconIndex')]" + } + } + ], + "outputs": { + "applicationResourceIds": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups/applications', parameters('appGroupName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed Application." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the AVD Application was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('appGroupName')]", + "metadata": { + "description": "The Name of the Application Group to register the Application in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "appGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppGroup-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "6125132429909581432" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8')]", + "Desktop Virtualization Application Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "Desktop Virtualization Workspace Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b')]", + "Desktop Virtualization Workspace Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD application group" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD application group was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD application group" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))]" + ] + } + ], + "outputs": { + "avdAppGroupsArray": { + "type": "array", + "copy": { + "count": "[length(variables('finalApplicationGroups'))]", + "input": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AppGroup-{0}-{1}', variables('finalApplicationGroups')[copyIndex()].name, parameters('time')))).outputs.resourceId.value]" + } + }, + "hostPooltoken": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))).outputs.hostPoolRestrationInfo.value.token]" + } + } + } + }, + "dependsOn": [ + "avdBaselineResourceGroups" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-WorkSpace-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdWorkSpaceName')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "appGroupResourceIds": { + "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-HostPool-AppGroups-{0}', parameters('time')))).outputs.avdAppGroupsArray.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15682861181301968290" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the workspace to be attach to new Application Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "appGroupResourceIds": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Required. Resource IDs fo the existing Application groups this workspace will group together." + } + }, + "workspaceFriendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Workspace to be created." + } + }, + "workspaceDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Workspace to be created." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management", + "Feed" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management", + "Feed" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DesktopVirtualization/workspaces", + "apiVersion": "2021-07-12", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "applicationGroupReferences": "[parameters('appGroupResourceIds')]", + "description": "[parameters('workspaceDescription')]", + "friendlyName": "[parameters('workspaceFriendlyName')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/workspaces/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/workspaces/{0}', parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + ] + }, + { + "copy": { + "name": "workspace_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Workspace-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "6906548022506531566" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization Workspace Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b')]", + "Desktop Virtualization Workspace Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/workspaces/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD workspace" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD workspace was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD workspace" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-HostPool-AppGroups-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "Create-ManagedIdentities-RoleAssign", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "avdComputeObjectsRgName": { + "value": "[variables('avdComputeObjectsRgName')]" + }, + "avdDeploySessionHosts": { + "value": "[parameters('avdDeploySessionHosts')]" + }, + "avdEnterpriseAppObjectId": { + "value": "[parameters('avdEnterpriseAppObjectId')]" + }, + "avdManagementPlaneLocation": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "avdServiceObjectsRgName": { + "value": "[variables('avdServiceObjectsRgName')]" + }, + "avdStorageObjectsRgName": { + "value": "[variables('avdStorageObjectsRgName')]" + }, + "avdWorkloadSubsId": { + "value": "[parameters('avdWorkloadSubsId')]" + }, + "createStartVmOnConnectCustomRole": { + "value": "[parameters('createStartVmOnConnectCustomRole')]" + }, + "fslogixManagedIdentityName": { + "value": "[variables('fslogixManagedIdentityName')]" + }, + "readerRoleId": { + "value": "[variables('readerRoleId')]" + }, + "storageAccountContributorRoleId": { + "value": "[variables('storageAccountContributorRoleId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2978116119221605503" + } + }, + "parameters": { + "avdManagementPlaneLocation": { + "type": "string", + "metadata": { + "description": "Required. Location where to deploy AVD management plane" + } + }, + "avdWorkloadSubsId": { + "type": "string", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdServiceObjectsRgName": { + "type": "string", + "metadata": { + "description": "AVD Resource Group Name for the service objects" + } + }, + "avdComputeObjectsRgName": { + "type": "string", + "metadata": { + "description": "Resource Group name for the session hosts" + } + }, + "avdStorageObjectsRgName": { + "type": "string", + "metadata": { + "description": "Resource Group Name for Azure Files" + } + }, + "avdEnterpriseAppObjectId": { + "type": "string", + "metadata": { + "description": "Azure Virtual Desktop enterprise application object ID" + } + }, + "createStartVmOnConnectCustomRole": { + "type": "bool", + "metadata": { + "description": "Create custom Start VM on connect role" + } + }, + "avdDeploySessionHosts": { + "type": "bool", + "metadata": { + "description": "Deploy new session hosts" + } + }, + "fslogixManagedIdentityName": { + "type": "string", + "metadata": { + "description": "FSlogix Managed Identity name" + } + }, + "readerRoleId": { + "type": "string", + "metadata": { + "description": "GUID for built role Reader" + } + }, + "storageAccountContributorRoleId": { + "type": "string", + "metadata": { + "description": "GUID for built in role ID of Storage Account Contributor" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "resources": [ + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('fslogix-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('fslogixManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1131211123076456844" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15620413071584694012" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + } + }, + { + "condition": "[parameters('createStartVmOnConnectCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Start-VM-on-Connect-Role-{0}', parameters('time'))]", + "subscriptionId": "[parameters('avdWorkloadSubsId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "subscriptionId": { + "value": "[parameters('avdWorkloadSubsId')]" + }, + "description": { + "value": "Start VM on connect AVD" + }, + "roleName": { + "value": "StartVMonConnect-AVD" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "actions": { + "value": [ + "Microsoft.Compute/virtualMachines/start/action", + "Microsoft.Compute/virtualMachines/*/read" + ] + }, + "assignableScopes": { + "value": [ + "[format('/subscriptions/{0}', parameters('avdWorkloadSubsId'))]" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15841945517409798363" + } + }, + "parameters": { + "roleName": { + "type": "string", + "metadata": { + "description": "Required. Name of the custom RBAC role to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the custom RBAC role to be created." + } + }, + "actions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed actions." + } + }, + "notActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied actions." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "notDataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "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." + } + }, + "assignableScopes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Role definition assignable scopes. If not provided, will use the current scope provided." + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location deployment metadata." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "location": "[parameters('location')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2018-01-01-preview", + "name": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "properties": { + "roleName": "[parameters('roleName')]", + "description": "[parameters('description')]", + "type": "customRole", + "permissions": [ + { + "actions": "[parameters('actions')]", + "notActions": "[parameters('notActions')]", + "dataActions": "[parameters('dataActions')]", + "notDataActions": "[parameters('notDataActions')]" + } + ], + "assignableScopes": "[if(not(empty(parameters('assignableScopes'))), parameters('assignableScopes'), array(subscription().id))]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "metadata": { + "description": "The GUID of the Role Definition" + } + }, + "scope": { + "type": "string", + "value": "[subscription().id]", + "metadata": { + "description": "The scope this Role Definition applies to" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Authorization/roleDefinitions', guid(parameters('roleName'), parameters('subscriptionId')))]", + "metadata": { + "description": "The resource ID of the Role Definition" + } + } + } + } + } + }, + { + "condition": "[parameters('createStartVmOnConnectCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Start-VM-OnConnect-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createStartVmOnConnectCustomRole'), reference(subscriptionResourceId(parameters('avdWorkloadSubsId'), 'Microsoft.Resources/deployments', format('Start-VM-on-Connect-Role-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value, '')]" + }, + "principalId": { + "value": "[parameters('avdEnterpriseAppObjectId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8666590821633789861" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdWorkloadSubsId'), 'Microsoft.Resources/deployments', format('Start-VM-on-Connect-Role-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('fslogix-UserAIdentity-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdStorageObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/{1}', parameters('avdWorkloadSubsId'), parameters('storageAccountContributorRoleId'))]" + }, + "principalId": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('fslogix-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.principalId.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8666590821633789861" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('fslogix-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('fslogix-UserAIdentity-ReaderRoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdStorageObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/{1}', parameters('avdWorkloadSubsId'), parameters('readerRoleId'))]" + }, + "principalId": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('fslogix-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.principalId.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8666590821633789861" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('fslogix-Managed-Identity-{0}', parameters('time')))]" + ] + } + ], + "outputs": { + "fslogixManagedIdentityResourceId": { + "type": "string", + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('fslogix-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value]" + } + } + } + }, + "dependsOn": [ + "avdBaselineResourceGroups" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Workload-KeyVault-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdWrklKvName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "enableRbacAuthorization": { + "value": false + }, + "enablePurgeProtection": { + "value": true + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "privateEndpoints": { + "value": "[if(parameters('avdVnetPrivateDnsZone'), createArray(createObject('subnetResourceId', if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdVirtualNetworkResourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId')), 'service', 'vault', 'privateDnsZoneResourceIds', createArray(parameters('avdVnetPrivateDnsZoneKeyvaultId')))), createArray(createObject('subnetResourceId', if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdVirtualNetworkResourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId')), 'service', 'vault')))]" + }, + "secrets": { + "value": { + "secureList": [ + { + "name": "avdVmLocalUserPassword", + "value": "[parameters('avdVmLocalUserPassword')]", + "contentType": "Session host local user credentials" + }, + { + "name": "avdVmLocalUserName", + "value": "[parameters('avdVmLocalUserName')]", + "contentType": "Session host local user credentials" + }, + { + "name": "avdDomainJoinUserName", + "value": "[parameters('avdDomainJoinUserName')]", + "contentType": "Domain join credentials" + }, + { + "name": "avdDomainJoinUserPassword", + "value": "[parameters('avdDomainJoinUserPassword')]", + "contentType": "Domain join credentials" + } + ] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7117964379708714511" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "maxLength": 24, + "metadata": { + "description": "Optional. Name of the Key Vault. If no name is provided, then unique name will be created." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of access policies object" + } + }, + "secrets": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. All secrets to create" + } + }, + "keys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. All keys to create" + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute" + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment" + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios." + } + }, + "enableSoftDelete": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "defaultValue": 90, + "metadata": { + "description": "Optional. softDelete data retention days. It accepts >=7 and <=90." + } + }, + "enableRbacAuthorization": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC." + } + }, + "createMode": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "vaultSku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault" + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "enabled", + "allowedValues": [ + "enabled", + "disabled" + ], + "metadata": { + "description": "Optional. Property to specify whether the vault will accept traffic from public internet. If set to \"disabled\" all traffic except private endpoint traffic and that that originates from trusted services will be blocked. This will override the set firewall rules, meaning that even if the firewall rules are present we will not honor the rules." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. " + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "AuditEvent", + "AzurePolicyEvaluationDetails" + ], + "allowedValues": [ + "AuditEvent", + "AzurePolicyEvaluationDetails" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ], + "maxNameLength": 24, + "uniquenameUntrim": "[uniqueString(format('Key Vault{0}', parameters('baseTime')))]", + "uniquename": "[if(greater(length(variables('uniquenameUntrim')), variables('maxNameLength')), substring(variables('uniquenameUntrim'), 0, variables('maxNameLength')), variables('uniquenameUntrim'))]", + "name_var": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniquename'))]", + "networkAcls_var": { + "bypass": "[if(not(empty(parameters('networkAcls'))), parameters('networkAcls').bypass, null())]", + "defaultAction": "[if(not(empty(parameters('networkAcls'))), parameters('networkAcls').defaultAction, null())]", + "virtualNetworkRules": "[if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'virtualNetworkRules')), parameters('networkAcls').virtualNetworkRules, createArray())]", + "ipRules": "[if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'ipRules')), parameters('networkAcls').ipRules, createArray())]" + }, + "secretList": "[if(not(empty(parameters('secrets'))), parameters('secrets').secureList, createArray())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2021-11-01-preview", + "name": "[variables('name_var')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "enabledForDeployment": "[parameters('enableVaultForDeployment')]", + "enabledForTemplateDeployment": "[parameters('enableVaultForTemplateDeployment')]", + "enabledForDiskEncryption": "[parameters('enableVaultForDiskEncryption')]", + "enableSoftDelete": "[parameters('enableSoftDelete')]", + "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]", + "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]", + "createMode": "[parameters('createMode')]", + "enablePurgeProtection": "[if(parameters('enablePurgeProtection'), parameters('enablePurgeProtection'), null())]", + "tenantId": "[subscription().tenantId]", + "accessPolicies": "[variables('formattedAccessPolicies')]", + "sku": { + "name": "[parameters('vaultSku')]", + "family": "A" + }, + "networkAcls": "[if(not(empty(parameters('networkAcls'))), variables('networkAcls_var'), null())]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-{1}-lock', variables('name_var'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "accessPolicies": { + "value": "[variables('formattedAccessPolicies')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16492524556919253664" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "defaultValue": "add", + "metadata": { + "description": "Optional. The access policy deployment" + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2021-06-01-preview", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the access policies assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the access policies assignment" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_secrets", + "count": "[length(variables('secretList'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('secretList')[copyIndex()].name]" + }, + "value": { + "value": "[variables('secretList')[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesEnabled'), variables('secretList')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesExp'), variables('secretList')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesNbf'), variables('secretList')[copyIndex()].attributesNbf, -1)]" + }, + "contentType": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'contentType'), variables('secretList')[copyIndex()].contentType, '')]" + }, + "tags": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'tags'), variables('secretList')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'roleAssignments'), variables('secretList')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9855184563194001290" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "secureString", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "value": "[parameters('value')]" + } + }, + { + "copy": { + "name": "secret_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "12822591518009644118" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the secret." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the secret." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the secret was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_keys", + "count": "[length(parameters('keys'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('keys')[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesEnabled'), parameters('keys')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesExp'), parameters('keys')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesNbf'), parameters('keys')[copyIndex()].attributesNbf, -1)]" + }, + "curveName": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'curveName'), parameters('keys')[copyIndex()].curveName, 'P-256')]" + }, + "keyOps": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keyOps'), parameters('keys')[copyIndex()].keyOps, createArray())]" + }, + "keySize": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keySize'), parameters('keys')[copyIndex()].keySize, -1)]" + }, + "kty": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'kty'), parameters('keys')[copyIndex()].kty, 'EC')]" + }, + "tags": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'tags'), parameters('keys')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'roleAssignments'), parameters('keys')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9202505798573795419" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "curveName": { + "type": "string", + "defaultValue": "P-256", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "metadata": { + "description": "Optional. The elliptic curve name." + } + }, + "keyOps": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation" + } + }, + "keySize": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA." + } + }, + "kty": { + "type": "string", + "defaultValue": "EC", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "metadata": { + "description": "Optional. The type of the key." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "curveName": "[parameters('curveName')]", + "keyOps": "[parameters('keyOps')]", + "keySize": "[if(not(equals(parameters('keySize'), -1)), parameters('keySize'), null())]", + "kty": "[parameters('kty')]" + } + }, + { + "copy": { + "name": "key_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8663685790625721754" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the key." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the key." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "14496837389589298146" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + }, + { + "condition": "[not(empty(variables('privateEndpoint_var').privateDnsZoneResourceIds))]", + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/default', variables('privateEndpoint_var').name)]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds)))]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15956299923651638071" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]", + "metadata": { + "description": "The resource ID of the key vault." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key vault was created in." + } + }, + "name": { + "type": "string", + "value": "[variables('name_var')]", + "metadata": { + "description": "The name of the key vault." + } + }, + "uri": { + "type": "string", + "value": "[reference(resourceId('Microsoft.KeyVault/vaults', variables('name_var'))).vaultUri]", + "metadata": { + "description": "The URI of the key vault." + } + } + } + } + }, + "dependsOn": [ + "avdBaselineResourceGroups", + "[subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-Storage-AzureFiles-{0}', parameters('time'))]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "addStorageToDomainScript": { + "value": "[variables('addStorageToDomainScript')]" + }, + "addStorageToDomainScriptArgs": { + "value": "[variables('addStorageToDomainScriptArgs')]" + }, + "addStorageToDomainScriptUri": { + "value": "[variables('addStorageToDomainScriptUri')]" + }, + "avdApplicationSecurityGroupResourceId": { + "value": "[if(parameters('createAvdVnet'), format('{0}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdApplicationSecurityGroupResourceId.value), '')]" + }, + "avdComputeObjectsRgName": { + "value": "[variables('avdComputeObjectsRgName')]" + }, + "avdDomainJoinUserName": { + "value": "[parameters('avdDomainJoinUserName')]" + }, + "avdDomainJoinUserPassword": { + "reference": { + "keyVault": { + "id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.KeyVault/vaults', variables('avdWrklKvName'))]" + }, + "secretName": "avdDomainJoinUserPassword" + } + }, + "avdFslogixFileShareName": { + "value": "[variables('avdFslogixFileShareName')]" + }, + "avdFslogixFileShareQuotaSize": { + "value": "[parameters('avdFslogixFileShareQuotaSize')]" + }, + "avdFslogixStorageName": { + "value": "[variables('avdFslogixStorageName')]" + }, + "avdIdentityDomainName": { + "value": "[parameters('avdIdentityDomainName')]" + }, + "avdImageTemplataDefinitionId": { + "value": "[parameters('avdImageTemplataDefinitionId')]" + }, + "avdOuPath": { + "value": "[parameters('avdOuPath')]" + }, + "avdSessionHostDiskType": { + "value": "[parameters('avdSessionHostDiskType')]" + }, + "avdSessionHostLocation": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "avdSessionHostsSize": { + "value": "[parameters('avdSessionHostsSize')]" + }, + "avdStorageObjectsRgName": { + "value": "[variables('avdStorageObjectsRgName')]" + }, + "avdSubnetId": { + "value": "[if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdVirtualNetworkResourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId'))]" + }, + "avdVmLocalUserName": { + "value": "[parameters('avdVmLocalUserName')]" + }, + "avdVmLocalUserPassword": { + "reference": { + "keyVault": { + "id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.KeyVault/vaults', variables('avdWrklKvName'))]" + }, + "secretName": "avdVmLocalUserPassword" + } + }, + "avdVnetPrivateDnsZone": { + "value": "[parameters('avdVnetPrivateDnsZone')]" + }, + "avdVnetPrivateDnsZoneFilesId": { + "value": "[parameters('avdVnetPrivateDnsZoneFilesId')]" + }, + "avdWorkloadSubsId": { + "value": "[parameters('avdWorkloadSubsId')]" + }, + "encryptionAtHost": { + "value": "[parameters('encryptionAtHost')]" + }, + "fslogixManagedIdentityResourceId": { + "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', 'Create-ManagedIdentities-RoleAssign')).outputs.fslogixManagedIdentityResourceId.value]" + }, + "fsLogixStorageSku": { + "value": "[parameters('fsLogixStorageSku')]" + }, + "marketPlaceGalleryWindows": { + "value": "[variables('marketPlaceGalleryWindows').win10_21h2]" + }, + "subnetResourceId": { + "value": "[if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdVirtualNetworkResourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId'))]" + }, + "tempStorageVmName": { + "value": "[variables('tempStorageVmName')]" + }, + "useSharedImage": { + "value": "[parameters('useSharedImage')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "10084569912377809770" + } + }, + "parameters": { + "avdComputeObjectsRgName": { + "type": "string", + "metadata": { + "description": "Resource Group name for the session hosts" + } + }, + "avdWorkloadSubsId": { + "type": "string", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdStorageObjectsRgName": { + "type": "string", + "metadata": { + "description": "Resource Group Name for Azure Files" + } + }, + "avdSubnetId": { + "type": "string", + "metadata": { + "description": "AVD subnet ID" + } + }, + "avdSessionHostLocation": { + "type": "string", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "encryptionAtHost": { + "type": "bool", + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "avdSessionHostsSize": { + "type": "string", + "metadata": { + "description": "Session host VM size (Defualt: Standard_D2s_v3) " + } + }, + "avdSessionHostDiskType": { + "type": "string", + "metadata": { + "description": "OS disk type for session host (Defualt: Standard_LRS) " + } + }, + "marketPlaceGalleryWindows": { + "type": "object", + "metadata": { + "description": "Market Place OS image" + } + }, + "useSharedImage": { + "type": "bool", + "metadata": { + "description": "Set to deploy image from Azure Compute Gallery" + } + }, + "avdImageTemplataDefinitionId": { + "type": "string", + "metadata": { + "description": "Source custom image ID" + } + }, + "fslogixManagedIdentityResourceId": { + "type": "string", + "metadata": { + "description": "Fslogix Managed Identity Resource ID " + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Subnet resource ID for the Azure Files private endpoint" + } + }, + "avdVmLocalUserName": { + "type": "string", + "metadata": { + "description": "Local administrator username" + } + }, + "avdVmLocalUserPassword": { + "type": "secureString", + "metadata": { + "description": "Local administrator password" + } + }, + "avdIdentityDomainName": { + "type": "string", + "metadata": { + "description": "Required. AD domain name" + } + }, + "avdDomainJoinUserName": { + "type": "string", + "metadata": { + "description": "Required. AVD session host domain join credentials" + } + }, + "avdDomainJoinUserPassword": { + "type": "secureString" + }, + "avdOuPath": { + "type": "string", + "metadata": { + "description": "Optional. OU path to join AVd VMs" + } + }, + "avdApplicationSecurityGroupResourceId": { + "type": "string", + "metadata": { + "description": "Application Security Group (ASG) for the session hosts" + } + }, + "avdFslogixStorageName": { + "type": "string", + "metadata": { + "description": "Azure Fies storage account name" + } + }, + "avdFslogixFileShareName": { + "type": "string", + "metadata": { + "description": "Azure Files share name" + } + }, + "fsLogixStorageSku": { + "type": "string", + "metadata": { + "description": "Azure Files storage account SKU" + } + }, + "avdFslogixFileShareQuotaSize": { + "type": "int", + "metadata": { + "description": "Azure File share quota" + } + }, + "avdVnetPrivateDnsZone": { + "type": "bool", + "metadata": { + "description": "Use Azure private DNS zones for private endpoints (Default: false)" + } + }, + "avdVnetPrivateDnsZoneFilesId": { + "type": "string", + "metadata": { + "description": "Use Azure private DNS zones for private endpoints (Default: false)" + } + }, + "tempStorageVmName": { + "type": "string", + "metadata": { + "description": "Name for temporary virtual machine. Used to join Azure Files to domain" + } + }, + "addStorageToDomainScript": { + "type": "string", + "metadata": { + "description": "Script name for adding storage account to Active Directory" + } + }, + "addStorageToDomainScriptArgs": { + "type": "string", + "metadata": { + "description": "Script arguments for adding the storage account to Active Directory" + } + }, + "addStorageToDomainScriptUri": { + "type": "string", + "metadata": { + "description": "URI for the script for adding the storage account to Active Directory" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Fslogix-Storage-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdStorageObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdFslogixStorageName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "storageAccountSku": { + "value": "[parameters('fsLogixStorageSku')]" + }, + "allowBlobPublicAccess": { + "value": false + }, + "storageAccountKind": { + "value": "[if(or(equals(toLower(parameters('fsLogixStorageSku')), toLower('Premium_LRS')), equals(toLower(parameters('fsLogixStorageSku')), toLower('Premium_ZRS'))), 'FileStorage', 'StorageV2')]" + }, + "storageAccountAccessTier": { + "value": "Hot" + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "fileServices": { + "value": { + "shares": [ + { + "name": "[parameters('avdFslogixFileShareName')]", + "shareQuota": "[mul(parameters('avdFslogixFileShareQuotaSize'), 100)]" + } + ] + } + }, + "privateEndpoints": { + "value": "[if(parameters('avdVnetPrivateDnsZone'), createArray(createObject('subnetResourceId', parameters('subnetResourceId'), 'service', 'file', 'privateDnsZoneResourceIds', createArray(parameters('avdVnetPrivateDnsZoneFilesId')))), createArray(createObject('subnetResourceId', parameters('subnetResourceId'), 'service', 'file')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2820787175439416263" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Storage Account. Autogenerated with a unique string if not provided." + }, + "maxLength": 24 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "storageAccountKind": { + "type": "string", + "defaultValue": "StorageV2", + "metadata": { + "description": "Optional. Type of Storage Account to create." + }, + "allowedValues": [ + "Storage", + "StorageV2", + "BlobStorage", + "FileStorage", + "BlockBlobStorage" + ] + }, + "storageAccountSku": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage Account Sku Name." + }, + "allowedValues": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS", + "Premium_ZRS", + "Standard_GZRS", + "Standard_RAGZRS" + ] + }, + "storageAccountAccessTier": { + "type": "string", + "defaultValue": "Hot", + "metadata": { + "description": "Optional. Storage Account Access Tier." + }, + "allowedValues": [ + "Hot", + "Cool" + ] + }, + "azureFilesIdentityBasedAuthentication": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Provides the identity based authentication settings for Azure Files." + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "managementPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Storage Account ManagementPolicies Rules." + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true." + } + }, + "blobServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Blob service and containers to deploy" + } + }, + "fileServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. File service and shares to deploy" + } + }, + "queueServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Queue service and queues to create." + } + }, + "tableServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Table service and tables to create." + } + }, + "allowBlobPublicAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "TLS1_2", + "metadata": { + "description": "Optional. Set the minimum TLS version on request to storage." + }, + "allowedValues": [ + "TLS1_0", + "TLS1_1", + "TLS1_2" + ] + }, + "enableHierarchicalNamespace": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If true, enables Hierarchical Namespace for the storage account" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "basetime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Enabled", + "metadata": { + "description": "Optional. Enable or disallow public network access to Storage Account.." + }, + "allowedValues": [ + "Enabled", + "Disabled" + ] + }, + "supportsHttpsTrafficOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Allows HTTPS traffic only to storage service if sets to true." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "maxNameLength": 24, + "uniqueStorageNameUntrim": "[format('{0}', uniqueString(format('Storage Account{0}', parameters('basetime'))))]", + "uniqueStorageName": "[if(greater(length(variables('uniqueStorageNameUntrim')), variables('maxNameLength')), substring(variables('uniqueStorageNameUntrim'), 0, variables('maxNameLength')), variables('uniqueStorageNameUntrim'))]", + "supportsBlobService": "[or(or(or(equals(parameters('storageAccountKind'), 'BlockBlobStorage'), equals(parameters('storageAccountKind'), 'BlobStorage')), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage'))]", + "supportsFileService": "[or(or(equals(parameters('storageAccountKind'), 'FileStorage'), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage'))]", + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2021-08-01", + "name": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]", + "location": "[parameters('location')]", + "kind": "[parameters('storageAccountKind')]", + "sku": { + "name": "[parameters('storageAccountSku')]" + }, + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "properties": { + "encryption": { + "keySource": "Microsoft.Storage", + "services": { + "blob": "[if(variables('supportsBlobService'), createObject('enabled', true()), null())]", + "file": "[if(variables('supportsFileService'), createObject('enabled', true()), null())]" + }, + "requireInfrastructureEncryption": "[if(not(equals(parameters('storageAccountKind'), 'Storage')), parameters('requireInfrastructureEncryption'), null())]" + }, + "accessTier": "[if(not(equals(parameters('storageAccountKind'), 'Storage')), parameters('storageAccountAccessTier'), null())]", + "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]", + "isHnsEnabled": "[if(parameters('enableHierarchicalNamespace'), parameters('enableHierarchicalNamespace'), null())]", + "minimumTlsVersion": "[parameters('minimumTlsVersion')]", + "networkAcls": "[if(not(empty(parameters('networkAcls'))), createObject('bypass', if(not(empty(parameters('networkAcls'))), parameters('networkAcls').bypass, null()), 'defaultAction', if(not(empty(parameters('networkAcls'))), parameters('networkAcls').defaultAction, null()), 'virtualNetworkRules', if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'virtualNetworkRules')), parameters('networkAcls').virtualNetworkRules, createArray()), 'ipRules', if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'ipRules')), parameters('networkAcls').ipRules, createArray())), null())]", + "allowBlobPublicAccess": "[parameters('allowBlobPublicAccess')]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "azureFilesIdentityBasedAuthentication": "[if(not(empty(parameters('azureFilesIdentityBasedAuthentication'))), parameters('azureFilesIdentityBasedAuthentication'), null())]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]", + "name": "[format('{0}-{1}-lock', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "copy": { + "name": "storageAccount_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16610301563380405946" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('privateEndpoints')))]", + "copy": { + "name": "storageAccount_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-PrivateEndpoints-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(not(empty(parameters('privateEndpoints'))), reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location, 'dummy')]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1106636052820512350" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/{1}', variables('privateEndpoint_var').name, 'default')]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(variables('privateEndpoint_var').privateDnsZoneResourceIds)]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('managementPolicyRules')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-ManagementPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "rules": { + "value": "[parameters('managementPolicyRules')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3253774105655355109" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the storage container to deploy" + } + }, + "rules": { + "type": "array", + "metadata": { + "description": "Required. The Storage Account ManagementPolicies Rules" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('rules')))]", + "type": "Microsoft.Storage/storageAccounts/managementPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "policy": { + "rules": "[parameters('rules')]" + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The resource ID of the deployed management policy" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed management policy" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed management policy" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('blobServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-BlobServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "containers": { + "value": "[if(contains(parameters('blobServices'), 'containers'), parameters('blobServices').containers, createArray())]" + }, + "automaticSnapshotPolicyEnabled": { + "value": "[if(contains(parameters('blobServices'), 'automaticSnapshotPolicyEnabled'), parameters('blobServices').automaticSnapshotPolicyEnabled, false())]" + }, + "deleteRetentionPolicy": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicy'), parameters('blobServices').deleteRetentionPolicy, true())]" + }, + "deleteRetentionPolicyDays": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicyDays'), parameters('blobServices').deleteRetentionPolicyDays, 7)]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogsRetentionInDays'), parameters('blobServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticStorageAccountId'), parameters('blobServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('blobServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubName'), parameters('blobServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogCategoriesToEnable'), parameters('blobServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticMetricsToEnable'), parameters('blobServices').diagnosticMetricsToEnable, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticWorkspaceId'), parameters('blobServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "5769438066360147349" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the blob service" + } + }, + "deleteRetentionPolicy": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service." + } + }, + "deleteRetentionPolicyDays": { + "type": "int", + "defaultValue": 7, + "metadata": { + "description": "Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365." + } + }, + "automaticSnapshotPolicyEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Automatic Snapshot is enabled if set to true." + } + }, + "containers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Blob containers to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "deleteRetentionPolicy": { + "enabled": "[parameters('deleteRetentionPolicy')]", + "days": "[parameters('deleteRetentionPolicyDays')]" + }, + "automaticSnapshotPolicyEnabled": "[parameters('automaticSnapshotPolicyEnabled')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "blobServices_container", + "count": "[length(parameters('containers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Container-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('containers')[copyIndex()].name]" + }, + "publicAccess": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'publicAccess'), parameters('containers')[copyIndex()].publicAccess, 'None')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'roleAssignments'), parameters('containers')[copyIndex()].roleAssignments, createArray())]" + }, + "immutabilityPolicyProperties": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'immutabilityPolicyProperties'), parameters('containers')[copyIndex()].immutabilityPolicyProperties, createObject())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7149162740350746791" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage container to deploy" + } + }, + "immutabilityPolicyName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "publicAccess": { + "type": "string", + "defaultValue": "None", + "metadata": { + "description": "Optional. Specifies whether data in the container may be accessed publicly and the level of access." + }, + "allowedValues": [ + "Container", + "Blob", + "None" + ] + }, + "immutabilityPolicyProperties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Configure immutability policy." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "properties": { + "publicAccess": "[parameters('publicAccess')]" + } + }, + { + "condition": "[not(empty(parameters('immutabilityPolicyProperties')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[parameters('immutabilityPolicyName')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('blobServicesName')]" + }, + "containerName": { + "value": "[parameters('name')]" + }, + "immutabilityPeriodSinceCreationInDays": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'immutabilityPeriodSinceCreationInDays'), parameters('immutabilityPolicyProperties').immutabilityPeriodSinceCreationInDays, 365)]" + }, + "allowProtectedAppendWrites": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'allowProtectedAppendWrites'), parameters('immutabilityPolicyProperties').allowProtectedAppendWrites, true())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "12805627095883262775" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "containerName": { + "type": "string", + "metadata": { + "description": "Required. Name of the container to apply the policy to" + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "immutabilityPeriodSinceCreationInDays": { + "type": "int", + "defaultValue": 365, + "metadata": { + "description": "Optional. The immutability period for the blobs in the container since the policy creation, in days." + } + }, + "allowProtectedAppendWrites": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "properties": { + "immutabilityPeriodSinceCreationInDays": "[parameters('immutabilityPeriodSinceCreationInDays')]", + "allowProtectedAppendWrites": "[parameters('allowProtectedAppendWrites')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed immutability policy." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed immutability policy." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed immutability policy." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "container_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2389940191716042805" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}/containers/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed container" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed container" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed container" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed blob service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed blob service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the deployed blob service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('fileServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-FileServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogsRetentionInDays'), parameters('fileServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticStorageAccountId'), parameters('fileServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('fileServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubName'), parameters('fileServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogCategoriesToEnable'), parameters('fileServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticMetricsToEnable'), parameters('fileServices').diagnosticMetricsToEnable, createArray())]" + }, + "protocolSettings": { + "value": "[if(contains(parameters('fileServices'), 'protocolSettings'), parameters('fileServices').protocolSettings, createObject())]" + }, + "shareDeleteRetentionPolicy": { + "value": "[if(contains(parameters('fileServices'), 'shareDeleteRetentionPolicy'), parameters('fileServices').shareDeleteRetentionPolicy, createObject('enabled', true(), 'days', 7))]" + }, + "shares": { + "value": "[if(contains(parameters('fileServices'), 'shares'), parameters('fileServices').shares, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticWorkspaceId'), parameters('fileServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15400523973338909377" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "protocolSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Protocol settings for file service" + } + }, + "shareDeleteRetentionPolicy": { + "type": "object", + "defaultValue": { + "enabled": true, + "days": 7 + }, + "metadata": { + "description": "Optional. The service properties for soft delete." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "shares": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. File shares to create." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "protocolSettings": "[parameters('protocolSettings')]", + "shareDeleteRetentionPolicy": "[parameters('shareDeleteRetentionPolicy')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "fileServices_shares", + "count": "[length(parameters('shares'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-shares-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "fileServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('shares')[copyIndex()].name]" + }, + "enabledProtocols": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'enabledProtocols'), parameters('shares')[copyIndex()].enabledProtocols, 'SMB')]" + }, + "rootSquash": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'rootSquash'), parameters('shares')[copyIndex()].rootSquash, 'NoRootSquash')]" + }, + "sharedQuota": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'sharedQuota'), parameters('shares')[copyIndex()].sharedQuota, 5120)]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'roleAssignments'), parameters('shares')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8012908004388630919" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "fileServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the file share to create" + } + }, + "sharedQuota": { + "type": "int", + "defaultValue": 5120, + "metadata": { + "description": "Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400." + } + }, + "enabledProtocols": { + "type": "string", + "defaultValue": "SMB", + "metadata": { + "description": "Optional. The authentication protocol that is used for the file share. Can only be specified when creating a share." + }, + "allowedValues": [ + "NFS", + "SMB" + ] + }, + "rootSquash": { + "type": "string", + "defaultValue": "NoRootSquash", + "metadata": { + "description": "Optional. Permissions for NFS file shares are enforced by the client OS rather than the Azure Files service. Toggling the root squash behavior reduces the rights of the root user for NFS shares." + }, + "allowedValues": [ + "AllSquash", + "NoRootSquash", + "RootSquash" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/fileServices/shares", + "apiVersion": "2021-08-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "properties": { + "shareQuota": "[parameters('sharedQuota')]", + "rootSquash": "[if(equals(parameters('enabledProtocols'), 'NFS'), parameters('rootSquash'), null())]", + "enabledProtocols": "[parameters('enabledProtocols')]" + } + }, + { + "copy": { + "name": "fileShare_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2512438268213117259" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}/shares/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('queueServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-QueueServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogsRetentionInDays'), parameters('queueServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticStorageAccountId'), parameters('queueServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('queueServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubName'), parameters('queueServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogCategoriesToEnable'), parameters('queueServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticMetricsToEnable'), parameters('queueServices').diagnosticMetricsToEnable, createArray())]" + }, + "queues": { + "value": "[if(contains(parameters('queueServices'), 'queues'), parameters('queueServices').queues, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticWorkspaceId'), parameters('queueServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15042600590518287455" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "queues": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Queues to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/queueServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "queueServices_queues", + "count": "[length(parameters('queues'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Queue-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "queueServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('queues')[copyIndex()].name]" + }, + "metadata": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'metadata'), parameters('queues')[copyIndex()].metadata, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'roleAssignments'), parameters('queues')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "5113461039331916331" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "queueServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage queue to deploy" + } + }, + "metadata": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Required. A name-value pair that represents queue metadata." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/queueServices/queues", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]" + } + }, + { + "copy": { + "name": "queue_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "11014868406062922847" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Dsms Role (deprecated)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b')]", + "Dsms Role (do not use)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f')]", + "GenevaWarmPathResourceContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}/queues/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed queue" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed queue" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed queue" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('tableServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-TableServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogsRetentionInDays'), parameters('tableServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticStorageAccountId'), parameters('tableServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('tableServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubName'), parameters('tableServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogCategoriesToEnable'), parameters('tableServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticMetricsToEnable'), parameters('tableServices').diagnosticMetricsToEnable, createArray())]" + }, + "tables": { + "value": "[if(contains(parameters('tableServices'), 'tables'), parameters('tableServices').tables, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticWorkspaceId'), parameters('tableServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16674693318462147203" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. tables to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/tableServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/tableServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "tableServices_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Table-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "tableServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()]]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3122726620958778940" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "tableServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/tableServices/tables", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]" + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices/tables', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed table service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed table service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed table service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]", + "metadata": { + "description": "The resource ID of the deployed storage account" + } + }, + "name": { + "type": "string", + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]", + "metadata": { + "description": "The name of the deployed storage account" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed storage account" + } + }, + "primaryBlobEndpoint": { + "type": "string", + "value": "[if(and(not(empty(parameters('blobServices'))), contains(parameters('blobServices'), 'containers')), reference(format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))), '2019-04-01').primaryEndpoints.blob, '')]", + "metadata": { + "description": "The primary blob endpoint reference if blob services are deployed." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))), '2021-08-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))), '2021-08-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-temporary-VM-FsLogixStorageToDomain-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdStorageObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('tempStorageVmName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "userAssignedIdentities": { + "value": { + "[format('{0}', parameters('fslogixManagedIdentityResourceId'))]": {} + } + }, + "encryptionAtHost": { + "value": "[parameters('encryptionAtHost')]" + }, + "availabilityZone": { + "value": [] + }, + "osType": { + "value": "Windows" + }, + "licenseType": { + "value": "Windows_Client" + }, + "vmSize": { + "value": "[parameters('avdSessionHostsSize')]" + }, + "imageReference": { + "value": "[if(parameters('useSharedImage'), json(format('{{''id'': ''{0}''}}', parameters('avdImageTemplataDefinitionId'))), parameters('marketPlaceGalleryWindows'))]" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": 128, + "managedDisk": { + "storageAccountType": "[parameters('avdSessionHostDiskType')]" + } + } + }, + "adminUsername": { + "value": "[parameters('avdVmLocalUserName')]" + }, + "adminPassword": { + "value": "[parameters('avdVmLocalUserPassword')]" + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "asgId": "[if(not(empty(parameters('avdApplicationSecurityGroupResourceId'))), parameters('avdApplicationSecurityGroupResourceId'), null())]", + "enableAcceleratedNetworking": false, + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "[parameters('avdSubnetId')]" + } + ] + } + ] + }, + "allowExtensionOperations": { + "value": true + }, + "extensionDomainJoinPassword": { + "value": "[parameters('avdDomainJoinUserPassword')]" + }, + "extensionDomainJoinConfig": { + "value": { + "enabled": true, + "settings": { + "name": "[parameters('avdIdentityDomainName')]", + "ouPath": "[if(not(empty(parameters('avdOuPath'))), parameters('avdOuPath'), null())]", + "user": "[parameters('avdDomainJoinUserName')]", + "restart": "true", + "options": "3" + } + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "11730108256333153621" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[take(toLower(uniqueString(resourceGroup().name)), 10)]", + "metadata": { + "description": "Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name." + } + }, + "vmComputerNamesTransformation": { + "type": "string", + "defaultValue": "none", + "metadata": { + "description": "Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'." + } + }, + "vmSize": { + "type": "string", + "metadata": { + "description": "Required. Specifies the size for the VMs" + } + }, + "encryptionAtHost": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "securityType": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings." + } + }, + "secureBootEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "vTpmEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "imageReference": { + "type": "object", + "metadata": { + "description": "Required. OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image." + } + }, + "plan": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use." + } + }, + "osDisk": { + "type": "object", + "metadata": { + "description": "Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "dataDisks": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "ultraSSDEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled." + } + }, + "adminUsername": { + "type": "secureString", + "metadata": { + "description": "Required. Administrator username" + } + }, + "adminPassword": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed" + } + }, + "customData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format." + } + }, + "certificatesToBeInstalled": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies set of certificates that should be installed onto the virtual machine." + } + }, + "vmPriority": { + "type": "string", + "defaultValue": "Regular", + "allowedValues": [ + "Regular", + "Low", + "Spot" + ], + "metadata": { + "description": "Optional. Specifies the priority for the virtual machine." + } + }, + "enableEvictionPolicy": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy." + } + }, + "maxPriceForLowPriorityVm": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars." + } + }, + "dedicatedHostId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies resource ID about the dedicated host that the virtual machine resides in." + } + }, + "licenseType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Windows_Client", + "Windows_Server", + "" + ], + "metadata": { + "description": "Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system." + } + }, + "publicKeys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The list of SSH public keys used to authenticate with linux based VMs" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "bootDiagnosticStorageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided." + } + }, + "bootDiagnosticStorageAccountUri": { + "type": "string", + "defaultValue": "[format('.blob.{0}/', environment().suffixes.storage)]", + "metadata": { + "description": "Optional. Storage account boot diagnostic base URI." + } + }, + "proximityPlacementGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource name of a proximity placement group." + } + }, + "availabilitySetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set." + } + }, + "availabilityZone": { + "type": "array", + "metadata": { + "description": "Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set." + } + }, + "nicConfigurations": { + "type": "array", + "metadata": { + "description": "Required. Configures NICs and PIPs." + } + }, + "pipDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the PIP diagnostic setting, if deployed." + } + }, + "pipdiagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "DDoSProtectionNotifications", + "DDoSMitigationFlowLogs", + "DDoSMitigationReports" + ], + "allowedValues": [ + "DDoSProtectionNotifications", + "DDoSMitigationFlowLogs", + "DDoSMitigationReports" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "pipdiagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "nicDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the NIC diagnostic setting, if deployed." + } + }, + "nicdiagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Recovery service vault name to add VMs to backup." + } + }, + "backupVaultResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "DefaultPolicy", + "metadata": { + "description": "Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault." + } + }, + "enableServerSideEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key." + } + }, + "allowExtensionOperations": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine." + } + }, + "extensionDomainJoinPassword": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter" + } + }, + "extensionDomainJoinConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Domain Join] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionAntiMalwareConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Anti Malware] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionMonitoringAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "monitoringWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true." + } + }, + "extensionDependencyAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Dependency Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionNetworkWatcherAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionDiskEncryptionConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Disk Encryption] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionDSCConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionCustomScriptConfig": { + "type": "object", + "defaultValue": { + "enabled": false, + "fileData": [] + }, + "metadata": { + "description": "Optional. The configuration for the [Custom Script] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionCustomScriptProtectedSetting": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The chosen OS type" + } + }, + "disablePasswordAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether password authentication should be disabled." + } + }, + "provisionVMAgent": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later." + } + }, + "enableAutomaticUpdates": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones." + } + }, + "additionalUnattendContent": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object" + } + }, + "winRM": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object." + } + }, + "configurationProfileAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Any VM configuration profile assignments" + } + } + }, + "variables": { + "copy": [ + { + "name": "publicKeysFormatted", + "count": "[length(parameters('publicKeys'))]", + "input": { + "path": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].path]", + "keyData": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].keyData]" + } + } + ], + "vmComputerNameTransformed": "[if(equals(parameters('vmComputerNamesTransformation'), 'uppercase'), toUpper(parameters('name')), if(equals(parameters('vmComputerNamesTransformation'), 'lowercase'), toLower(parameters('name')), parameters('name')))]", + "linuxConfiguration": { + "disablePasswordAuthentication": "[parameters('disablePasswordAuthentication')]", + "ssh": { + "publicKeys": "[variables('publicKeysFormatted')]" + }, + "provisionVMAgent": "[parameters('provisionVMAgent')]" + }, + "windowsConfiguration": { + "provisionVMAgent": "[parameters('provisionVMAgent')]", + "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[if(empty(parameters('timeZone')), null(), parameters('timeZone'))]", + "additionalUnattendContent": "[if(empty(parameters('additionalUnattendContent')), null(), parameters('additionalUnattendContent'))]", + "winRM": "[if(not(empty(parameters('winRM'))), createObject('listeners', parameters('winRM')), null())]" + }, + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + }, + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2021-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "zones": "[if(equals(parameters('availabilityZone'), ''), null(), parameters('availabilityZone'))]", + "plan": "[if(not(empty(parameters('plan'))), parameters('plan'), null())]", + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "securityProfile": { + "encryptionAtHost": "[if(parameters('encryptionAtHost'), parameters('encryptionAtHost'), null())]", + "securityType": "[parameters('securityType')]", + "uefiSettings": "[if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())]" + }, + "storageProfile": { + "copy": [ + { + "name": "dataDisks", + "count": "[length(parameters('dataDisks'))]", + "input": { + "lun": "[copyIndex('dataDisks')]", + "name": "[format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0'))]", + "diskSizeGB": "[parameters('dataDisks')[copyIndex('dataDisks')].diskSizeGB]", + "createOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'createOption'), parameters('dataDisks')[copyIndex('dataDisks')].createOption, 'Empty')]", + "deleteOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'deleteOption'), parameters('dataDisks')[copyIndex('dataDisks')].deleteOption, 'Delete')]", + "caching": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'caching'), parameters('dataDisks')[copyIndex('dataDisks')].caching, 'ReadOnly')]", + "managedDisk": { + "storageAccountType": "[parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.storageAccountType]", + "diskEncryptionSet": { + "id": "[if(parameters('enableServerSideEncryption'), parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.diskEncryptionSet.id, null())]" + } + } + } + } + ], + "imageReference": "[parameters('imageReference')]", + "osDisk": { + "name": "[format('{0}-disk-os-01', parameters('name'))]", + "createOption": "[if(contains(parameters('osDisk'), 'createOption'), parameters('osDisk').createOption, 'FromImage')]", + "deleteOption": "[if(contains(parameters('osDisk'), 'deleteOption'), parameters('osDisk').deleteOption, 'Delete')]", + "diskSizeGB": "[parameters('osDisk').diskSizeGB]", + "caching": "[if(contains(parameters('osDisk'), 'caching'), parameters('osDisk').caching, 'ReadOnly')]", + "managedDisk": { + "storageAccountType": "[parameters('osDisk').managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('osDisk').managedDisk, 'diskEncryptionSet'), parameters('osDisk').managedDisk.diskEncryptionSet, null())]" + } + } + }, + "additionalCapabilities": { + "ultraSSDEnabled": "[parameters('ultraSSDEnabled')]" + }, + "osProfile": { + "computerName": "[variables('vmComputerNameTransformed')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]", + "customData": "[if(not(empty(parameters('customData'))), base64(parameters('customData')), null())]", + "windowsConfiguration": "[if(equals(parameters('osType'), 'Windows'), variables('windowsConfiguration'), null())]", + "linuxConfiguration": "[if(equals(parameters('osType'), 'Linux'), variables('linuxConfiguration'), null())]", + "secrets": "[parameters('certificatesToBeInstalled')]", + "allowExtensionOperations": "[parameters('allowExtensionOperations')]" + }, + "networkProfile": { + "copy": [ + { + "name": "networkInterfaces", + "count": "[length(parameters('nicConfigurations'))]", + "input": { + "properties": { + "deleteOption": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaces')], 'deleteOption'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].deleteOption, 'Delete')]", + "primary": "[if(equals(copyIndex('networkInterfaces'), 0), true(), false())]" + }, + "id": "[resourceId('Microsoft.Network/networkInterfaces', format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].nicSuffix))]" + } + } + ] + }, + "diagnosticsProfile": { + "bootDiagnostics": { + "enabled": "[not(empty(parameters('bootDiagnosticStorageAccountName')))]", + "storageUri": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), format('https://{0}{1}', parameters('bootDiagnosticStorageAccountName'), parameters('bootDiagnosticStorageAccountUri')), null())]" + } + }, + "availabilitySet": "[if(not(empty(parameters('availabilitySetName'))), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySetName')))), null())]", + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupName'))), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Compute/proximityPlacementGroups', parameters('proximityPlacementGroupName')))), null())]", + "priority": "[parameters('vmPriority')]", + "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", + "billingProfile": "[if(and(not(empty(parameters('vmPriority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), json(format('{{\"maxPrice\":\"{0}\"}}', parameters('maxPriceForLowPriorityVm'))), null())]", + "host": "[if(not(empty(parameters('dedicatedHostId'))), json(format('{{\"id\":\"{0}\"}}', parameters('dedicatedHostId'))), null())]", + "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]" + }, + "dependsOn": [ + "virtualMachine_nic" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "copy": { + "name": "virtualMachine_nic", + "count": "[length(parameters('nicConfigurations'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Nic-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "networkInterfaceName": { + "value": "[format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex()].nicSuffix)]" + }, + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "enableIPForwarding": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableIPForwarding'), if(not(empty(parameters('nicConfigurations')[copyIndex()].enableIPForwarding)), parameters('nicConfigurations')[copyIndex()].enableIPForwarding, false()), false())]" + }, + "enableAcceleratedNetworking": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableAcceleratedNetworking'), parameters('nicConfigurations')[copyIndex()].enableAcceleratedNetworking, true())]" + }, + "dnsServers": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'dnsServers'), if(not(empty(parameters('nicConfigurations')[copyIndex()].dnsServers)), parameters('nicConfigurations')[copyIndex()].dnsServers, createArray()), createArray())]" + }, + "networkSecurityGroupId": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'nsgId'), if(not(empty(parameters('nicConfigurations')[copyIndex()].nsgId)), parameters('nicConfigurations')[copyIndex()].nsgId, ''), '')]" + }, + "ipConfigurationArray": { + "value": "[parameters('nicConfigurations')[copyIndex()].ipConfigurations]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "diagnosticStorageAccountId": { + "value": "[parameters('diagnosticStorageAccountId')]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[parameters('diagnosticLogsRetentionInDays')]" + }, + "diagnosticWorkspaceId": { + "value": "[parameters('diagnosticWorkspaceId')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[parameters('diagnosticEventHubAuthorizationRuleId')]" + }, + "diagnosticEventHubName": { + "value": "[parameters('diagnosticEventHubName')]" + }, + "pipDiagnosticSettingsName": { + "value": "[parameters('pipDiagnosticSettingsName')]" + }, + "nicDiagnosticSettingsName": { + "value": "[parameters('nicDiagnosticSettingsName')]" + }, + "pipdiagnosticMetricsToEnable": { + "value": "[parameters('pipdiagnosticMetricsToEnable')]" + }, + "pipdiagnosticLogCategoriesToEnable": { + "value": "[parameters('pipdiagnosticLogCategoriesToEnable')]" + }, + "nicDiagnosticMetricsToEnable": { + "value": "[parameters('nicdiagnosticMetricsToEnable')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'roleAssignments'), if(not(empty(parameters('nicConfigurations')[copyIndex()].roleAssignments)), parameters('nicConfigurations')[copyIndex()].roleAssignments, createArray()), createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16118060021320950110" + } + }, + "parameters": { + "networkInterfaceName": { + "type": "string" + }, + "virtualMachineName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "tags": { + "type": "object" + }, + "enableIPForwarding": { + "type": "bool", + "defaultValue": false + }, + "enableAcceleratedNetworking": { + "type": "bool", + "defaultValue": false + }, + "dnsServers": { + "type": "array", + "defaultValue": [] + }, + "networkSecurityGroupId": { + "type": "string", + "defaultValue": "" + }, + "ipConfigurationArray": { + "type": "array" + }, + "lock": { + "type": "string" + }, + "diagnosticStorageAccountId": { + "type": "string" + }, + "diagnosticLogsRetentionInDays": { + "type": "int" + }, + "diagnosticWorkspaceId": { + "type": "string" + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string" + }, + "diagnosticEventHubName": { + "type": "string" + }, + "pipdiagnosticMetricsToEnable": { + "type": "array" + }, + "pipdiagnosticLogCategoriesToEnable": { + "type": "array" + }, + "nicDiagnosticMetricsToEnable": { + "type": "array" + }, + "roleAssignments": { + "type": "array" + }, + "pipDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('virtualMachineName'))]", + "metadata": { + "description": "Optional. The name of the PIP diagnostic setting, if deployed." + } + }, + "nicDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('virtualMachineName'))]", + "metadata": { + "description": "Optional. The name of the NIC diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "nicDiagnosticsMetrics", + "count": "[length(parameters('nicDiagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('nicDiagnosticMetricsToEnable')[copyIndex('nicDiagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2021-05-01", + "name": "[parameters('networkInterfaceName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "ipConfigurations", + "count": "[length(parameters('ipConfigurationArray'))]", + "input": { + "name": "[if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].name)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].name, null())]", + "properties": { + "primary": "[if(equals(copyIndex('ipConfigurations'), 0), true(), false())]", + "privateIPAllocationMethod": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].privateIPAllocationMethod)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].privateIPAllocationMethod, null()), null())]", + "privateIPAddress": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'vmIPAddress'), if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].vmIPAddress)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].vmIPAddress, null()), null())]", + "publicIPAddress": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'pipconfiguration'), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Network/publicIPAddresses', format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].pipconfiguration.publicIpNameSuffix)))), null())]", + "subnet": { + "id": "[parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].subnetId]" + }, + "loadBalancerBackendAddressPools": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'loadBalancerBackendAddressPools'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].loadBalancerBackendAddressPools, null())]", + "applicationSecurityGroups": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'applicationSecurityGroups'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].applicationSecurityGroups, null())]" + } + } + } + ], + "enableIPForwarding": "[parameters('enableIPForwarding')]", + "enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]", + "dnsSettings": "[if(not(empty(parameters('dnsServers'))), createObject('dnsServers', parameters('dnsServers')), null())]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupId'))), createObject('id', parameters('networkSecurityGroupId')), null())]" + }, + "dependsOn": [ + "networkInterface_publicIPConfigurations" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('networkInterfaceName'))]", + "name": "[format('{0}-{1}-lock', parameters('networkInterfaceName'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('networkInterfaceName'))]", + "name": "[parameters('nicDiagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('nicDiagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + }, + { + "condition": "[contains(parameters('ipConfigurationArray')[copyIndex()], 'pipconfiguration')]", + "copy": { + "name": "networkInterface_publicIPConfigurations", + "count": "[length(parameters('ipConfigurationArray'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-PIP-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "publicIPAddressName": { + "value": "[format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIpNameSuffix)]" + }, + "publicIPPrefixId": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'publicIPPrefixId'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPPrefixId)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPPrefixId, ''), '')]" + }, + "publicIPAllocationMethod": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'publicIPAllocationMethod'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPAllocationMethod)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPAllocationMethod, 'Static'), 'Static')]" + }, + "skuName": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'skuName'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuName)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuName, 'Standard'), 'Standard')]" + }, + "skuTier": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'skuTier'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuTier)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuTier, 'Regional'), 'Regional')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "diagnosticStorageAccountId": { + "value": "[parameters('diagnosticStorageAccountId')]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[parameters('diagnosticLogsRetentionInDays')]" + }, + "diagnosticWorkspaceId": { + "value": "[parameters('diagnosticWorkspaceId')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[parameters('diagnosticEventHubAuthorizationRuleId')]" + }, + "diagnosticEventHubName": { + "value": "[parameters('diagnosticEventHubName')]" + }, + "diagnosticSettingsName": { + "value": "[parameters('pipDiagnosticSettingsName')]" + }, + "diagnosticMetricsToEnable": { + "value": "[parameters('pipdiagnosticMetricsToEnable')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[parameters('pipdiagnosticLogCategoriesToEnable')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'roleAssignments'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.roleAssignments)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.roleAssignments, createArray()), createArray())]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "13837974348429468530" + } + }, + "parameters": { + "publicIPAddressName": { + "type": "string" + }, + "publicIPPrefixId": { + "type": "string" + }, + "publicIPAllocationMethod": { + "type": "string" + }, + "skuName": { + "type": "string" + }, + "skuTier": { + "type": "string" + }, + "location": { + "type": "string" + }, + "diagnosticStorageAccountId": { + "type": "string" + }, + "diagnosticLogsRetentionInDays": { + "type": "int" + }, + "diagnosticWorkspaceId": { + "type": "string" + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string" + }, + "diagnosticEventHubName": { + "type": "string" + }, + "diagnosticMetricsToEnable": { + "type": "array" + }, + "diagnosticLogCategoriesToEnable": { + "type": "array" + }, + "lock": { + "type": "string" + }, + "roleAssignments": { + "type": "array" + }, + "tags": { + "type": "object" + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('publicIPAddressName'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2021-05-01", + "name": "[parameters('publicIPAddressName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "properties": { + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIPPrefixId'))), createObject('id', parameters('publicIPPrefixId')), null())]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('publicIPAddressName'))]", + "name": "[format('{0}-{1}-lock', parameters('publicIPAddressName'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('publicIPAddressName'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + }, + { + "copy": { + "name": "publicIpAddress_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16984565221218234256" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the public IP address was deployed." + } + }, + "name": { + "type": "string", + "value": "[parameters('publicIPAddressName')]", + "metadata": { + "description": "The name of the public IP address." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]", + "metadata": { + "description": "The resource ID of the public IP address." + } + } + } + } + } + }, + { + "copy": { + "name": "networkInterface_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "6321019982012504437" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + } + ] + } + } + }, + { + "copy": { + "name": "vm_configurationProfileAssignment", + "count": "[length(parameters('configurationProfileAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-ConfigurationProfileAssignment-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "configurationProfile": { + "value": "[parameters('configurationProfileAssignments')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9356269901594916535" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the configuration profile assignment" + } + }, + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the VM to be associated" + } + }, + "configurationProfile": { + "type": "string", + "allowedValues": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest" + ], + "metadata": { + "description": "Required. The configuration profile of automanage" + } + } + }, + "resources": [ + { + "type": "Microsoft.Automanage/configurationProfileAssignments", + "apiVersion": "2021-04-30-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('virtualMachineName'))]", + "name": "[parameters('name')]", + "properties": { + "configurationProfile": "[parameters('configurationProfile')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[extensionResourceId(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName')), 'Microsoft.Automanage/configurationProfileAssignments', parameters('name'))]", + "metadata": { + "description": "The resource ID of the configuration profile assignment" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the configuration profile assignment" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the configuration profile assignment was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDomainJoinConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DomainJoin" + }, + "publisher": { + "value": "Microsoft.Compute" + }, + "type": { + "value": "JsonADDomainExtension" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'typeHandlerVersion'), parameters('extensionDomainJoinConfig').typeHandlerVersion, '1.3')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDomainJoinConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'enableAutomaticUpgrade'), parameters('extensionDomainJoinConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[parameters('extensionDomainJoinConfig').settings]" + }, + "protectedSettings": { + "value": { + "Password": "[parameters('extensionDomainJoinPassword')]" + } + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionAntiMalwareConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftAntiMalware" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "IaaSAntimalware" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'typeHandlerVersion'), parameters('extensionAntiMalwareConfig').typeHandlerVersion, '1.3')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'autoUpgradeMinorVersion'), parameters('extensionAntiMalwareConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'enableAutomaticUpgrade'), parameters('extensionAntiMalwareConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[parameters('extensionAntiMalwareConfig').settings]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionMonitoringAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftMonitoringAgent" + }, + "publisher": { + "value": "Microsoft.EnterpriseCloud.Monitoring" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'MicrosoftMonitoringAgent', 'OmsAgentForLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'typeHandlerVersion'), parameters('extensionMonitoringAgentConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '1.0', '1.7'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionMonitoringAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionMonitoringAgentConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": { + "workspaceId": "[if(not(empty(parameters('monitoringWorkspaceId'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('monitoringWorkspaceId'), '/')[2], split(parameters('monitoringWorkspaceId'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(parameters('monitoringWorkspaceId'), '/'))), '2021-06-01').customerId, '')]" + } + }, + "protectedSettings": { + "value": { + "workspaceKey": "[if(not(empty(parameters('monitoringWorkspaceId'))), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('monitoringWorkspaceId'), '/')[2], split(parameters('monitoringWorkspaceId'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(parameters('monitoringWorkspaceId'), '/'))), '2021-06-01').primarySharedKey, '')]" + } + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDependencyAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DependencyAgent" + }, + "publisher": { + "value": "Microsoft.Azure.Monitoring.DependencyAgent" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'DependencyAgentWindows', 'DependencyAgentLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'typeHandlerVersion'), parameters('extensionDependencyAgentConfig').typeHandlerVersion, '9.5')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDependencyAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionDependencyAgentConfig').enableAutomaticUpgrade, true())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionNetworkWatcherAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "NetworkWatcherAgent" + }, + "publisher": { + "value": "Microsoft.Azure.NetworkWatcher" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'NetworkWatcherAgentWindows', 'NetworkWatcherAgentLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'typeHandlerVersion'), parameters('extensionNetworkWatcherAgentConfig').typeHandlerVersion, '1.4')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionNetworkWatcherAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionNetworkWatcherAgentConfig').enableAutomaticUpgrade, false())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDSCConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DesiredStateConfiguration" + }, + "publisher": { + "value": "Microsoft.Powershell" + }, + "type": { + "value": "DSC" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'typeHandlerVersion'), parameters('extensionDSCConfig').typeHandlerVersion, '2.77')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDSCConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'enableAutomaticUpgrade'), parameters('extensionDSCConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'settings'), parameters('extensionDSCConfig').settings, createObject())]" + }, + "protectedSettings": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'protectedSettings'), parameters('extensionDSCConfig').protectedSettings, createObject())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionCustomScriptConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "CustomScriptExtension" + }, + "publisher": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'Microsoft.Compute', 'Microsoft.Azure.Extensions')]" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'CustomScriptExtension', 'CustomScript')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'typeHandlerVersion'), parameters('extensionCustomScriptConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '1.10', '2.1'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'autoUpgradeMinorVersion'), parameters('extensionCustomScriptConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'enableAutomaticUpgrade'), parameters('extensionCustomScriptConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": { + "copy": [ + { + "name": "fileUris", + "count": "[length(parameters('extensionCustomScriptConfig').fileData)]", + "input": "[if(contains(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')], 'storageAccountId'), format('{0}?{1}', parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri, listAccountSas(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].storageAccountId, '2019-04-01', variables('accountSasProperties')).accountSasToken), parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri)]" + } + ] + } + }, + "protectedSettings": { + "value": "[parameters('extensionCustomScriptProtectedSetting')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "condition": "[parameters('extensionDiskEncryptionConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DiskEncryption', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DiskEncryption" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'AzureDiskEncryption', 'AzureDiskEncryptionForLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'typeHandlerVersion'), parameters('extensionDiskEncryptionConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '2.2', '1.1'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDiskEncryptionConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'enableAutomaticUpgrade'), parameters('extensionDiskEncryptionConfig').enableAutomaticUpgrade, false())]" + }, + "forceUpdateTag": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'forceUpdateTag'), parameters('extensionDiskEncryptionConfig').forceUpdateTag, '1.0')]" + }, + "settings": { + "value": "[parameters('extensionDiskEncryptionConfig').settings]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "condition": "[not(empty(parameters('backupVaultName')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Backup', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[parameters('backupVaultResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "backupResourceName": { + "value": "[format('{0}/Azure/iaasvmcontainer;iaasvmcontainerv2;{1};{2}/vm;iaasvmcontainerv2;{3};{4}', parameters('backupVaultName'), resourceGroup().name, parameters('name'), resourceGroup().name, parameters('name'))]" + }, + "protectedItemType": { + "value": "Microsoft.Compute/virtualMachines" + }, + "backupPolicyId": { + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('backupVaultName'), parameters('backupPolicyName'))]" + }, + "sourceResourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "4804590430499663077" + } + }, + "parameters": { + "backupResourceName": { + "type": "string" + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ] + }, + "backupPolicyId": { + "type": "string" + }, + "sourceResourceId": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2021-06-01", + "name": "[parameters('backupResourceName')]", + "location": "[resourceGroup().location]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('backupPolicyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "copy": { + "name": "virtualMachine_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "14627441919207189649" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the VM." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "metadata": { + "description": "The resource ID of the VM." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the VM was created in." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), '2021-07-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), '2021-07-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdStorageObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Fslogix-Storage-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Add-FslogixStorage-to-ADDS-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdStorageObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "name": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdStorageObjectsRgName'))), 'Microsoft.Resources/deployments', format('Deploy-temporary-VM-FsLogixStorageToDomain-{0}', parameters('time')))).outputs.name.value]" + }, + "file": { + "value": "[parameters('addStorageToDomainScript')]" + }, + "ScriptArguments": { + "value": "[parameters('addStorageToDomainScriptArgs')]" + }, + "baseScriptUri": { + "value": "[parameters('addStorageToDomainScriptUri')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17457825769105795292" + } + }, + "parameters": { + "name": { + "type": "string" + }, + "location": { + "type": "string" + }, + "baseScriptUri": { + "type": "string" + }, + "file": { + "type": "string" + }, + "ScriptArguments": { + "type": "secureString" + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/addAzureFilesToADDSScript', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Compute", + "type": "CustomScriptExtension", + "typeHandlerVersion": "1.10", + "autoUpgradeMinorVersion": true, + "settings": {}, + "protectedSettings": { + "fileUris": "[array(parameters('baseScriptUri'))]", + "commandToExecute": "[format('powershell -ExecutionPolicy Unrestricted -File {0} {1}', parameters('file'), parameters('ScriptArguments'))]" + } + } + } + ] + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdStorageObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Fslogix-Storage-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdStorageObjectsRgName'))), 'Microsoft.Resources/deployments', format('Deploy-temporary-VM-FsLogixStorageToDomain-{0}', parameters('time')))]" + ] + } + ] + } + }, + "dependsOn": [ + "avdBaselineResourceGroups", + "[subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time')))]", + "[subscriptionResourceId('Microsoft.Resources/deployments', 'Create-ManagedIdentities-RoleAssign')]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-and-Configure-AVD-SessionHosts-{0}', parameters('time'))]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "avdAgentPackageLocation": { + "value": "[variables('avdAgentPackageLocation')]" + }, + "avdApplicationSecurityGroupResourceId": { + "value": "[if(parameters('createAvdVnet'), format('{0}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdApplicationSecurityGroupResourceId.value), '')]" + }, + "avdAsFaultDomainCount": { + "value": "[parameters('avdAsFaultDomainCount')]" + }, + "avdAsUpdateDomainCount": { + "value": "[parameters('avdAsUpdateDomainCount')]" + }, + "avdAvailabilitySetName": { + "value": "[variables('avdAvailabilitySetName')]" + }, + "avdComputeObjectsRgName": { + "value": "[variables('avdComputeObjectsRgName')]" + }, + "avdDeploySessionHostsCount": { + "value": "[parameters('avdDeploySessionHostsCount')]" + }, + "avdDomainJoinUserName": { + "value": "[parameters('avdDomainJoinUserName')]" + }, + "avdDomainJoinUserPassword": { + "reference": { + "keyVault": { + "id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.KeyVault/vaults', variables('avdWrklKvName'))]" + }, + "secretName": "avdDomainJoinUserPassword" + } + }, + "avdHostPoolName": { + "value": "[variables('avdHostPoolName')]" + }, + "avdIdentityDomainName": { + "value": "[parameters('avdIdentityDomainName')]" + }, + "avdImageTemplataDefinitionId": { + "value": "[parameters('avdImageTemplataDefinitionId')]" + }, + "avdOuPath": { + "value": "[parameters('avdOuPath')]" + }, + "avdSessionHostDiskType": { + "value": "[parameters('avdSessionHostDiskType')]" + }, + "avdSessionHostLocation": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "avdSessionHostNamePrefix": { + "value": "[variables('avdSessionHostNamePrefix')]" + }, + "avdSessionHostsSize": { + "value": "[parameters('avdSessionHostsSize')]" + }, + "avdSubnetId": { + "value": "[if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time'))), '2020-10-01').outputs.avdVirtualNetworkResourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId'))]" + }, + "avdUseAvailabilityZones": { + "value": "[parameters('avdUseAvailabilityZones')]" + }, + "avdVmLocalUserName": { + "value": "[parameters('avdVmLocalUserName')]" + }, + "avdVmLocalUserPassword": { + "reference": { + "keyVault": { + "id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.KeyVault/vaults', variables('avdWrklKvName'))]" + }, + "secretName": "avdVmLocalUserPassword" + } + }, + "avdWorkloadSubsId": { + "value": "[parameters('avdWorkloadSubsId')]" + }, + "encryptionAtHost": { + "value": "[parameters('encryptionAtHost')]" + }, + "fslogixManagedIdentityResourceId": { + "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', 'Create-ManagedIdentities-RoleAssign')).outputs.fslogixManagedIdentityResourceId.value]" + }, + "fsLogixScript": { + "value": "[variables('fsLogixScript')]" + }, + "FsLogixScriptArguments": { + "value": "[variables('FsLogixScriptArguments')]" + }, + "fslogixScriptUri": { + "value": "[variables('fslogixScriptUri')]" + }, + "hostPoolToken": { + "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-HostPool-AppGroups-{0}', parameters('time')))).outputs.hostPooltoken.value]" + }, + "marketPlaceGalleryWindows": { + "value": "[variables('marketPlaceGalleryWindows')[parameters('avdOsImage')]]" + }, + "useSharedImage": { + "value": "[parameters('useSharedImage')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "190303758976101054" + } + }, + "parameters": { + "avdSubnetId": { + "type": "string", + "metadata": { + "description": "AVD subnet ID" + } + }, + "avdSessionHostLocation": { + "type": "string", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "avdSessionHostNamePrefix": { + "type": "string", + "metadata": { + "description": "AVD Session Host prefix" + } + }, + "avdComputeObjectsRgName": { + "type": "string", + "metadata": { + "description": "Resource Group name for the session hosts" + } + }, + "avdWorkloadSubsId": { + "type": "string", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdDeploySessionHostsCount": { + "type": "int", + "metadata": { + "description": "Quantity of session hosts to deploy" + } + }, + "avdUseAvailabilityZones": { + "type": "bool", + "metadata": { + "description": "Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)" + } + }, + "avdAvailabilitySetName": { + "type": "string", + "metadata": { + "description": "Optional. Availablity Set name" + } + }, + "avdAsFaultDomainCount": { + "type": "int", + "metadata": { + "description": "Optional. Sets the number of fault domains for the availability set. (Defualt: 3)" + } + }, + "avdAsUpdateDomainCount": { + "type": "int", + "metadata": { + "description": "Optional. Sets the number of update domains for the availability set. (Defualt: 5)" + } + }, + "encryptionAtHost": { + "type": "bool", + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "avdSessionHostsSize": { + "type": "string", + "metadata": { + "description": "Session host VM size (Defualt: Standard_D2s_v3) " + } + }, + "avdSessionHostDiskType": { + "type": "string", + "metadata": { + "description": "OS disk type for session host (Defualt: Standard_LRS) " + } + }, + "marketPlaceGalleryWindows": { + "type": "object", + "metadata": { + "description": "Market Place OS image" + } + }, + "useSharedImage": { + "type": "bool", + "metadata": { + "description": "Set to deploy image from Azure Compute Gallery" + } + }, + "avdImageTemplataDefinitionId": { + "type": "string", + "metadata": { + "description": "Source custom image ID" + } + }, + "fslogixManagedIdentityResourceId": { + "type": "string", + "metadata": { + "description": "Fslogix Managed Identity Resource ID " + } + }, + "avdVmLocalUserName": { + "type": "string", + "metadata": { + "description": "Local administrator username" + } + }, + "avdVmLocalUserPassword": { + "type": "secureString", + "metadata": { + "description": "Local administrator password" + } + }, + "avdIdentityDomainName": { + "type": "string", + "metadata": { + "description": "Required. AD domain name" + } + }, + "avdDomainJoinUserName": { + "type": "string", + "metadata": { + "description": "Required. AVD session host domain join credentials" + } + }, + "avdDomainJoinUserPassword": { + "type": "secureString" + }, + "avdOuPath": { + "type": "string", + "metadata": { + "description": "Optional. OU path to join AVd VMs" + } + }, + "avdApplicationSecurityGroupResourceId": { + "type": "string", + "metadata": { + "description": "Application Security Group (ASG) for the session hosts" + } + }, + "hostPoolToken": { + "type": "string", + "metadata": { + "description": "AVD host pool token" + } + }, + "avdHostPoolName": { + "type": "string", + "metadata": { + "description": "AVD Host Pool name" + } + }, + "avdAgentPackageLocation": { + "type": "string", + "metadata": { + "description": "Location for the AVD agent installation package. " + } + }, + "fsLogixScript": { + "type": "string", + "metadata": { + "description": "FSlogix configuration script file name. " + } + }, + "FsLogixScriptArguments": { + "type": "string", + "metadata": { + "description": "Configuration arguments for FSlogix" + } + }, + "fslogixScriptUri": { + "type": "string", + "metadata": { + "description": "URI for FSlogix configuration script" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "variables": { + "allAvailabilityZones": "[pickZones('Microsoft.Compute', 'virtualMachines', parameters('avdSessionHostLocation'), 3)]" + }, + "resources": [ + { + "condition": "[not(parameters('avdUseAvailabilityZones'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Availability-Set-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('avdAvailabilitySetName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "availabilitySetFaultDomain": { + "value": "[parameters('avdAsFaultDomainCount')]" + }, + "availabilitySetUpdateDomain": { + "value": "[parameters('avdAsUpdateDomainCount')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "12739234420863164896" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the availability set that is being created." + } + }, + "availabilitySetFaultDomain": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "Optional. The number of fault domains to use." + } + }, + "availabilitySetUpdateDomain": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Optional. The number of update domains to use." + } + }, + "availabilitySetSku": { + "type": "string", + "defaultValue": "Aligned", + "metadata": { + "description": "Optional. SKU of the availability set.\r\n- Use \\'Aligned\\' for virtual machines with managed disks\r\n- Use \\'Classic\\' for virtual machines with unmanaged disks.\r\n" + } + }, + "proximityPlacementGroupId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a proximity placement group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Resource location." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the availability set resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/availabilitySets", + "apiVersion": "2021-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "platformFaultDomainCount": "[parameters('availabilitySetFaultDomain')]", + "platformUpdateDomainCount": "[parameters('availabilitySetUpdateDomain')]", + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupId'))), createObject('id', parameters('proximityPlacementGroupId')), null())]" + }, + "sku": { + "name": "[parameters('availabilitySetSku')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/availabilitySets/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]" + ] + }, + { + "copy": { + "name": "availabilitySet_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AvSet-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "12095238983221849782" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/availabilitySets/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the availability set" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]", + "metadata": { + "description": "The resource ID of the availability set" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the availability set was deployed into" + } + } + } + } + } + }, + { + "copy": { + "name": "avdSessionHosts", + "count": "[length(range(0, parameters('avdDeploySessionHostsCount')))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Session-Host-{0}-{1}', range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}', parameters('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()])]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "userAssignedIdentities": { + "value": { + "[format('{0}', parameters('fslogixManagedIdentityResourceId'))]": {} + } + }, + "availabilityZone": { + "value": "[if(parameters('avdUseAvailabilityZones'), take(skip(variables('allAvailabilityZones'), mod(range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], length(variables('allAvailabilityZones')))), 1), createArray())]" + }, + "encryptionAtHost": { + "value": "[parameters('encryptionAtHost')]" + }, + "availabilitySetName": { + "value": "[if(not(parameters('avdUseAvailabilityZones')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Availability-Set-{0}', parameters('time'))), '2020-10-01').outputs.name.value, '')]" + }, + "osType": { + "value": "Windows" + }, + "licenseType": { + "value": "Windows_Client" + }, + "vmSize": { + "value": "[parameters('avdSessionHostsSize')]" + }, + "imageReference": { + "value": "[if(parameters('useSharedImage'), json(format('{{''id'': ''{0}''}}', parameters('avdImageTemplataDefinitionId'))), parameters('marketPlaceGalleryWindows'))]" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": 128, + "managedDisk": { + "storageAccountType": "[parameters('avdSessionHostDiskType')]" + } + } + }, + "adminUsername": { + "value": "[parameters('avdVmLocalUserName')]" + }, + "adminPassword": { + "value": "[parameters('avdVmLocalUserPassword')]" + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "asgId": "[if(not(empty(parameters('avdApplicationSecurityGroupResourceId'))), parameters('avdApplicationSecurityGroupResourceId'), null())]", + "enableAcceleratedNetworking": false, + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "[parameters('avdSubnetId')]" + } + ] + } + ] + }, + "allowExtensionOperations": { + "value": true + }, + "extensionDomainJoinPassword": { + "value": "[parameters('avdDomainJoinUserPassword')]" + }, + "extensionDomainJoinConfig": { + "value": { + "enabled": true, + "settings": { + "name": "[parameters('avdIdentityDomainName')]", + "ouPath": "[if(not(empty(parameters('avdOuPath'))), parameters('avdOuPath'), null())]", + "user": "[parameters('avdDomainJoinUserName')]", + "restart": "true", + "options": "3" + } + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "isEnabled": "true", + "day": "7", + "time": "120", + "scanType": "Quick" + }, + "Exclusions": { + "Extensions": "*.vhd;*.vhdx", + "Paths": "\"%ProgramFiles%\\FSLogix\\Apps\\frxdrv.sys;%ProgramFiles%\\FSLogix\\Apps\\frxccd.sys;%ProgramFiles%\\FSLogix\\Apps\\frxdrvvt.sys;%TEMP%\\*.VHD;%TEMP%\\*.VHDX;%Windir%\\TEMP\\*.VHD;%Windir%\\TEMP\\*.VHDX;\\\\server\\share\\*\\*.VHD;\\\\server\\share\\*\\*.VHDX", + "Processes": "%ProgramFiles%\\FSLogix\\Apps\\frxccd.exe;%ProgramFiles%\\FSLogix\\Apps\\frxccds.exe;%ProgramFiles%\\FSLogix\\Apps\\frxsvc.exe" + } + } + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "11730108256333153621" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[take(toLower(uniqueString(resourceGroup().name)), 10)]", + "metadata": { + "description": "Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name." + } + }, + "vmComputerNamesTransformation": { + "type": "string", + "defaultValue": "none", + "metadata": { + "description": "Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'." + } + }, + "vmSize": { + "type": "string", + "metadata": { + "description": "Required. Specifies the size for the VMs" + } + }, + "encryptionAtHost": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "securityType": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings." + } + }, + "secureBootEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "vTpmEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "imageReference": { + "type": "object", + "metadata": { + "description": "Required. OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image." + } + }, + "plan": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use." + } + }, + "osDisk": { + "type": "object", + "metadata": { + "description": "Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "dataDisks": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "ultraSSDEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled." + } + }, + "adminUsername": { + "type": "secureString", + "metadata": { + "description": "Required. Administrator username" + } + }, + "adminPassword": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed" + } + }, + "customData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format." + } + }, + "certificatesToBeInstalled": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies set of certificates that should be installed onto the virtual machine." + } + }, + "vmPriority": { + "type": "string", + "defaultValue": "Regular", + "allowedValues": [ + "Regular", + "Low", + "Spot" + ], + "metadata": { + "description": "Optional. Specifies the priority for the virtual machine." + } + }, + "enableEvictionPolicy": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy." + } + }, + "maxPriceForLowPriorityVm": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars." + } + }, + "dedicatedHostId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies resource ID about the dedicated host that the virtual machine resides in." + } + }, + "licenseType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Windows_Client", + "Windows_Server", + "" + ], + "metadata": { + "description": "Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system." + } + }, + "publicKeys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The list of SSH public keys used to authenticate with linux based VMs" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "bootDiagnosticStorageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided." + } + }, + "bootDiagnosticStorageAccountUri": { + "type": "string", + "defaultValue": "[format('.blob.{0}/', environment().suffixes.storage)]", + "metadata": { + "description": "Optional. Storage account boot diagnostic base URI." + } + }, + "proximityPlacementGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource name of a proximity placement group." + } + }, + "availabilitySetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set." + } + }, + "availabilityZone": { + "type": "array", + "metadata": { + "description": "Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set." + } + }, + "nicConfigurations": { + "type": "array", + "metadata": { + "description": "Required. Configures NICs and PIPs." + } + }, + "pipDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the PIP diagnostic setting, if deployed." + } + }, + "pipdiagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "DDoSProtectionNotifications", + "DDoSMitigationFlowLogs", + "DDoSMitigationReports" + ], + "allowedValues": [ + "DDoSProtectionNotifications", + "DDoSMitigationFlowLogs", + "DDoSMitigationReports" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "pipdiagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "nicDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the NIC diagnostic setting, if deployed." + } + }, + "nicdiagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Recovery service vault name to add VMs to backup." + } + }, + "backupVaultResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "DefaultPolicy", + "metadata": { + "description": "Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault." + } + }, + "enableServerSideEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key." + } + }, + "allowExtensionOperations": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine." + } + }, + "extensionDomainJoinPassword": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter" + } + }, + "extensionDomainJoinConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Domain Join] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionAntiMalwareConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Anti Malware] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionMonitoringAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "monitoringWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true." + } + }, + "extensionDependencyAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Dependency Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionNetworkWatcherAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionDiskEncryptionConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Disk Encryption] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionDSCConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionCustomScriptConfig": { + "type": "object", + "defaultValue": { + "enabled": false, + "fileData": [] + }, + "metadata": { + "description": "Optional. The configuration for the [Custom Script] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionCustomScriptProtectedSetting": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The chosen OS type" + } + }, + "disablePasswordAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether password authentication should be disabled." + } + }, + "provisionVMAgent": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later." + } + }, + "enableAutomaticUpdates": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones." + } + }, + "additionalUnattendContent": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object" + } + }, + "winRM": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object." + } + }, + "configurationProfileAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Any VM configuration profile assignments" + } + } + }, + "variables": { + "copy": [ + { + "name": "publicKeysFormatted", + "count": "[length(parameters('publicKeys'))]", + "input": { + "path": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].path]", + "keyData": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].keyData]" + } + } + ], + "vmComputerNameTransformed": "[if(equals(parameters('vmComputerNamesTransformation'), 'uppercase'), toUpper(parameters('name')), if(equals(parameters('vmComputerNamesTransformation'), 'lowercase'), toLower(parameters('name')), parameters('name')))]", + "linuxConfiguration": { + "disablePasswordAuthentication": "[parameters('disablePasswordAuthentication')]", + "ssh": { + "publicKeys": "[variables('publicKeysFormatted')]" + }, + "provisionVMAgent": "[parameters('provisionVMAgent')]" + }, + "windowsConfiguration": { + "provisionVMAgent": "[parameters('provisionVMAgent')]", + "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[if(empty(parameters('timeZone')), null(), parameters('timeZone'))]", + "additionalUnattendContent": "[if(empty(parameters('additionalUnattendContent')), null(), parameters('additionalUnattendContent'))]", + "winRM": "[if(not(empty(parameters('winRM'))), createObject('listeners', parameters('winRM')), null())]" + }, + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + }, + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2021-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "zones": "[if(equals(parameters('availabilityZone'), ''), null(), parameters('availabilityZone'))]", + "plan": "[if(not(empty(parameters('plan'))), parameters('plan'), null())]", + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "securityProfile": { + "encryptionAtHost": "[if(parameters('encryptionAtHost'), parameters('encryptionAtHost'), null())]", + "securityType": "[parameters('securityType')]", + "uefiSettings": "[if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())]" + }, + "storageProfile": { + "copy": [ + { + "name": "dataDisks", + "count": "[length(parameters('dataDisks'))]", + "input": { + "lun": "[copyIndex('dataDisks')]", + "name": "[format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0'))]", + "diskSizeGB": "[parameters('dataDisks')[copyIndex('dataDisks')].diskSizeGB]", + "createOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'createOption'), parameters('dataDisks')[copyIndex('dataDisks')].createOption, 'Empty')]", + "deleteOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'deleteOption'), parameters('dataDisks')[copyIndex('dataDisks')].deleteOption, 'Delete')]", + "caching": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'caching'), parameters('dataDisks')[copyIndex('dataDisks')].caching, 'ReadOnly')]", + "managedDisk": { + "storageAccountType": "[parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.storageAccountType]", + "diskEncryptionSet": { + "id": "[if(parameters('enableServerSideEncryption'), parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.diskEncryptionSet.id, null())]" + } + } + } + } + ], + "imageReference": "[parameters('imageReference')]", + "osDisk": { + "name": "[format('{0}-disk-os-01', parameters('name'))]", + "createOption": "[if(contains(parameters('osDisk'), 'createOption'), parameters('osDisk').createOption, 'FromImage')]", + "deleteOption": "[if(contains(parameters('osDisk'), 'deleteOption'), parameters('osDisk').deleteOption, 'Delete')]", + "diskSizeGB": "[parameters('osDisk').diskSizeGB]", + "caching": "[if(contains(parameters('osDisk'), 'caching'), parameters('osDisk').caching, 'ReadOnly')]", + "managedDisk": { + "storageAccountType": "[parameters('osDisk').managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('osDisk').managedDisk, 'diskEncryptionSet'), parameters('osDisk').managedDisk.diskEncryptionSet, null())]" + } + } + }, + "additionalCapabilities": { + "ultraSSDEnabled": "[parameters('ultraSSDEnabled')]" + }, + "osProfile": { + "computerName": "[variables('vmComputerNameTransformed')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]", + "customData": "[if(not(empty(parameters('customData'))), base64(parameters('customData')), null())]", + "windowsConfiguration": "[if(equals(parameters('osType'), 'Windows'), variables('windowsConfiguration'), null())]", + "linuxConfiguration": "[if(equals(parameters('osType'), 'Linux'), variables('linuxConfiguration'), null())]", + "secrets": "[parameters('certificatesToBeInstalled')]", + "allowExtensionOperations": "[parameters('allowExtensionOperations')]" + }, + "networkProfile": { + "copy": [ + { + "name": "networkInterfaces", + "count": "[length(parameters('nicConfigurations'))]", + "input": { + "properties": { + "deleteOption": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaces')], 'deleteOption'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].deleteOption, 'Delete')]", + "primary": "[if(equals(copyIndex('networkInterfaces'), 0), true(), false())]" + }, + "id": "[resourceId('Microsoft.Network/networkInterfaces', format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].nicSuffix))]" + } + } + ] + }, + "diagnosticsProfile": { + "bootDiagnostics": { + "enabled": "[not(empty(parameters('bootDiagnosticStorageAccountName')))]", + "storageUri": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), format('https://{0}{1}', parameters('bootDiagnosticStorageAccountName'), parameters('bootDiagnosticStorageAccountUri')), null())]" + } + }, + "availabilitySet": "[if(not(empty(parameters('availabilitySetName'))), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySetName')))), null())]", + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupName'))), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Compute/proximityPlacementGroups', parameters('proximityPlacementGroupName')))), null())]", + "priority": "[parameters('vmPriority')]", + "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", + "billingProfile": "[if(and(not(empty(parameters('vmPriority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), json(format('{{\"maxPrice\":\"{0}\"}}', parameters('maxPriceForLowPriorityVm'))), null())]", + "host": "[if(not(empty(parameters('dedicatedHostId'))), json(format('{{\"id\":\"{0}\"}}', parameters('dedicatedHostId'))), null())]", + "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]" + }, + "dependsOn": [ + "virtualMachine_nic" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "copy": { + "name": "virtualMachine_nic", + "count": "[length(parameters('nicConfigurations'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Nic-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "networkInterfaceName": { + "value": "[format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex()].nicSuffix)]" + }, + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "enableIPForwarding": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableIPForwarding'), if(not(empty(parameters('nicConfigurations')[copyIndex()].enableIPForwarding)), parameters('nicConfigurations')[copyIndex()].enableIPForwarding, false()), false())]" + }, + "enableAcceleratedNetworking": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableAcceleratedNetworking'), parameters('nicConfigurations')[copyIndex()].enableAcceleratedNetworking, true())]" + }, + "dnsServers": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'dnsServers'), if(not(empty(parameters('nicConfigurations')[copyIndex()].dnsServers)), parameters('nicConfigurations')[copyIndex()].dnsServers, createArray()), createArray())]" + }, + "networkSecurityGroupId": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'nsgId'), if(not(empty(parameters('nicConfigurations')[copyIndex()].nsgId)), parameters('nicConfigurations')[copyIndex()].nsgId, ''), '')]" + }, + "ipConfigurationArray": { + "value": "[parameters('nicConfigurations')[copyIndex()].ipConfigurations]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "diagnosticStorageAccountId": { + "value": "[parameters('diagnosticStorageAccountId')]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[parameters('diagnosticLogsRetentionInDays')]" + }, + "diagnosticWorkspaceId": { + "value": "[parameters('diagnosticWorkspaceId')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[parameters('diagnosticEventHubAuthorizationRuleId')]" + }, + "diagnosticEventHubName": { + "value": "[parameters('diagnosticEventHubName')]" + }, + "pipDiagnosticSettingsName": { + "value": "[parameters('pipDiagnosticSettingsName')]" + }, + "nicDiagnosticSettingsName": { + "value": "[parameters('nicDiagnosticSettingsName')]" + }, + "pipdiagnosticMetricsToEnable": { + "value": "[parameters('pipdiagnosticMetricsToEnable')]" + }, + "pipdiagnosticLogCategoriesToEnable": { + "value": "[parameters('pipdiagnosticLogCategoriesToEnable')]" + }, + "nicDiagnosticMetricsToEnable": { + "value": "[parameters('nicdiagnosticMetricsToEnable')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'roleAssignments'), if(not(empty(parameters('nicConfigurations')[copyIndex()].roleAssignments)), parameters('nicConfigurations')[copyIndex()].roleAssignments, createArray()), createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16118060021320950110" + } + }, + "parameters": { + "networkInterfaceName": { + "type": "string" + }, + "virtualMachineName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "tags": { + "type": "object" + }, + "enableIPForwarding": { + "type": "bool", + "defaultValue": false + }, + "enableAcceleratedNetworking": { + "type": "bool", + "defaultValue": false + }, + "dnsServers": { + "type": "array", + "defaultValue": [] + }, + "networkSecurityGroupId": { + "type": "string", + "defaultValue": "" + }, + "ipConfigurationArray": { + "type": "array" + }, + "lock": { + "type": "string" + }, + "diagnosticStorageAccountId": { + "type": "string" + }, + "diagnosticLogsRetentionInDays": { + "type": "int" + }, + "diagnosticWorkspaceId": { + "type": "string" + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string" + }, + "diagnosticEventHubName": { + "type": "string" + }, + "pipdiagnosticMetricsToEnable": { + "type": "array" + }, + "pipdiagnosticLogCategoriesToEnable": { + "type": "array" + }, + "nicDiagnosticMetricsToEnable": { + "type": "array" + }, + "roleAssignments": { + "type": "array" + }, + "pipDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('virtualMachineName'))]", + "metadata": { + "description": "Optional. The name of the PIP diagnostic setting, if deployed." + } + }, + "nicDiagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('virtualMachineName'))]", + "metadata": { + "description": "Optional. The name of the NIC diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "nicDiagnosticsMetrics", + "count": "[length(parameters('nicDiagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('nicDiagnosticMetricsToEnable')[copyIndex('nicDiagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2021-05-01", + "name": "[parameters('networkInterfaceName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "ipConfigurations", + "count": "[length(parameters('ipConfigurationArray'))]", + "input": { + "name": "[if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].name)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].name, null())]", + "properties": { + "primary": "[if(equals(copyIndex('ipConfigurations'), 0), true(), false())]", + "privateIPAllocationMethod": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].privateIPAllocationMethod)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].privateIPAllocationMethod, null()), null())]", + "privateIPAddress": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'vmIPAddress'), if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].vmIPAddress)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].vmIPAddress, null()), null())]", + "publicIPAddress": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'pipconfiguration'), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Network/publicIPAddresses', format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].pipconfiguration.publicIpNameSuffix)))), null())]", + "subnet": { + "id": "[parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].subnetId]" + }, + "loadBalancerBackendAddressPools": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'loadBalancerBackendAddressPools'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].loadBalancerBackendAddressPools, null())]", + "applicationSecurityGroups": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'applicationSecurityGroups'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].applicationSecurityGroups, null())]" + } + } + } + ], + "enableIPForwarding": "[parameters('enableIPForwarding')]", + "enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]", + "dnsSettings": "[if(not(empty(parameters('dnsServers'))), createObject('dnsServers', parameters('dnsServers')), null())]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupId'))), createObject('id', parameters('networkSecurityGroupId')), null())]" + }, + "dependsOn": [ + "networkInterface_publicIPConfigurations" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('networkInterfaceName'))]", + "name": "[format('{0}-{1}-lock', parameters('networkInterfaceName'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('networkInterfaceName'))]", + "name": "[parameters('nicDiagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('nicDiagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + }, + { + "condition": "[contains(parameters('ipConfigurationArray')[copyIndex()], 'pipconfiguration')]", + "copy": { + "name": "networkInterface_publicIPConfigurations", + "count": "[length(parameters('ipConfigurationArray'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-PIP-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "publicIPAddressName": { + "value": "[format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIpNameSuffix)]" + }, + "publicIPPrefixId": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'publicIPPrefixId'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPPrefixId)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPPrefixId, ''), '')]" + }, + "publicIPAllocationMethod": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'publicIPAllocationMethod'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPAllocationMethod)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPAllocationMethod, 'Static'), 'Static')]" + }, + "skuName": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'skuName'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuName)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuName, 'Standard'), 'Standard')]" + }, + "skuTier": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'skuTier'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuTier)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuTier, 'Regional'), 'Regional')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "diagnosticStorageAccountId": { + "value": "[parameters('diagnosticStorageAccountId')]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[parameters('diagnosticLogsRetentionInDays')]" + }, + "diagnosticWorkspaceId": { + "value": "[parameters('diagnosticWorkspaceId')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[parameters('diagnosticEventHubAuthorizationRuleId')]" + }, + "diagnosticEventHubName": { + "value": "[parameters('diagnosticEventHubName')]" + }, + "diagnosticSettingsName": { + "value": "[parameters('pipDiagnosticSettingsName')]" + }, + "diagnosticMetricsToEnable": { + "value": "[parameters('pipdiagnosticMetricsToEnable')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[parameters('pipdiagnosticLogCategoriesToEnable')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'roleAssignments'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.roleAssignments)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.roleAssignments, createArray()), createArray())]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "13837974348429468530" + } + }, + "parameters": { + "publicIPAddressName": { + "type": "string" + }, + "publicIPPrefixId": { + "type": "string" + }, + "publicIPAllocationMethod": { + "type": "string" + }, + "skuName": { + "type": "string" + }, + "skuTier": { + "type": "string" + }, + "location": { + "type": "string" + }, + "diagnosticStorageAccountId": { + "type": "string" + }, + "diagnosticLogsRetentionInDays": { + "type": "int" + }, + "diagnosticWorkspaceId": { + "type": "string" + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string" + }, + "diagnosticEventHubName": { + "type": "string" + }, + "diagnosticMetricsToEnable": { + "type": "array" + }, + "diagnosticLogCategoriesToEnable": { + "type": "array" + }, + "lock": { + "type": "string" + }, + "roleAssignments": { + "type": "array" + }, + "tags": { + "type": "object" + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('publicIPAddressName'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2021-05-01", + "name": "[parameters('publicIPAddressName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "properties": { + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIPPrefixId'))), createObject('id', parameters('publicIPPrefixId')), null())]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('publicIPAddressName'))]", + "name": "[format('{0}-{1}-lock', parameters('publicIPAddressName'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('publicIPAddressName'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + }, + { + "copy": { + "name": "publicIpAddress_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16984565221218234256" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the public IP address was deployed." + } + }, + "name": { + "type": "string", + "value": "[parameters('publicIPAddressName')]", + "metadata": { + "description": "The name of the public IP address." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]", + "metadata": { + "description": "The resource ID of the public IP address." + } + } + } + } + } + }, + { + "copy": { + "name": "networkInterface_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "6321019982012504437" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + } + ] + } + } + }, + { + "copy": { + "name": "vm_configurationProfileAssignment", + "count": "[length(parameters('configurationProfileAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-ConfigurationProfileAssignment-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "configurationProfile": { + "value": "[parameters('configurationProfileAssignments')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9356269901594916535" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the configuration profile assignment" + } + }, + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the VM to be associated" + } + }, + "configurationProfile": { + "type": "string", + "allowedValues": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest" + ], + "metadata": { + "description": "Required. The configuration profile of automanage" + } + } + }, + "resources": [ + { + "type": "Microsoft.Automanage/configurationProfileAssignments", + "apiVersion": "2021-04-30-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('virtualMachineName'))]", + "name": "[parameters('name')]", + "properties": { + "configurationProfile": "[parameters('configurationProfile')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[extensionResourceId(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName')), 'Microsoft.Automanage/configurationProfileAssignments', parameters('name'))]", + "metadata": { + "description": "The resource ID of the configuration profile assignment" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the configuration profile assignment" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the configuration profile assignment was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDomainJoinConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DomainJoin" + }, + "publisher": { + "value": "Microsoft.Compute" + }, + "type": { + "value": "JsonADDomainExtension" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'typeHandlerVersion'), parameters('extensionDomainJoinConfig').typeHandlerVersion, '1.3')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDomainJoinConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'enableAutomaticUpgrade'), parameters('extensionDomainJoinConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[parameters('extensionDomainJoinConfig').settings]" + }, + "protectedSettings": { + "value": { + "Password": "[parameters('extensionDomainJoinPassword')]" + } + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionAntiMalwareConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftAntiMalware" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "IaaSAntimalware" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'typeHandlerVersion'), parameters('extensionAntiMalwareConfig').typeHandlerVersion, '1.3')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'autoUpgradeMinorVersion'), parameters('extensionAntiMalwareConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'enableAutomaticUpgrade'), parameters('extensionAntiMalwareConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[parameters('extensionAntiMalwareConfig').settings]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionMonitoringAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftMonitoringAgent" + }, + "publisher": { + "value": "Microsoft.EnterpriseCloud.Monitoring" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'MicrosoftMonitoringAgent', 'OmsAgentForLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'typeHandlerVersion'), parameters('extensionMonitoringAgentConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '1.0', '1.7'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionMonitoringAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionMonitoringAgentConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": { + "workspaceId": "[if(not(empty(parameters('monitoringWorkspaceId'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('monitoringWorkspaceId'), '/')[2], split(parameters('monitoringWorkspaceId'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(parameters('monitoringWorkspaceId'), '/'))), '2021-06-01').customerId, '')]" + } + }, + "protectedSettings": { + "value": { + "workspaceKey": "[if(not(empty(parameters('monitoringWorkspaceId'))), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('monitoringWorkspaceId'), '/')[2], split(parameters('monitoringWorkspaceId'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(parameters('monitoringWorkspaceId'), '/'))), '2021-06-01').primarySharedKey, '')]" + } + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDependencyAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DependencyAgent" + }, + "publisher": { + "value": "Microsoft.Azure.Monitoring.DependencyAgent" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'DependencyAgentWindows', 'DependencyAgentLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'typeHandlerVersion'), parameters('extensionDependencyAgentConfig').typeHandlerVersion, '9.5')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDependencyAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionDependencyAgentConfig').enableAutomaticUpgrade, true())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionNetworkWatcherAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "NetworkWatcherAgent" + }, + "publisher": { + "value": "Microsoft.Azure.NetworkWatcher" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'NetworkWatcherAgentWindows', 'NetworkWatcherAgentLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'typeHandlerVersion'), parameters('extensionNetworkWatcherAgentConfig').typeHandlerVersion, '1.4')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionNetworkWatcherAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionNetworkWatcherAgentConfig').enableAutomaticUpgrade, false())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDSCConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DesiredStateConfiguration" + }, + "publisher": { + "value": "Microsoft.Powershell" + }, + "type": { + "value": "DSC" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'typeHandlerVersion'), parameters('extensionDSCConfig').typeHandlerVersion, '2.77')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDSCConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'enableAutomaticUpgrade'), parameters('extensionDSCConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'settings'), parameters('extensionDSCConfig').settings, createObject())]" + }, + "protectedSettings": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'protectedSettings'), parameters('extensionDSCConfig').protectedSettings, createObject())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionCustomScriptConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "CustomScriptExtension" + }, + "publisher": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'Microsoft.Compute', 'Microsoft.Azure.Extensions')]" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'CustomScriptExtension', 'CustomScript')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'typeHandlerVersion'), parameters('extensionCustomScriptConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '1.10', '2.1'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'autoUpgradeMinorVersion'), parameters('extensionCustomScriptConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'enableAutomaticUpgrade'), parameters('extensionCustomScriptConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": { + "copy": [ + { + "name": "fileUris", + "count": "[length(parameters('extensionCustomScriptConfig').fileData)]", + "input": "[if(contains(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')], 'storageAccountId'), format('{0}?{1}', parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri, listAccountSas(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].storageAccountId, '2019-04-01', variables('accountSasProperties')).accountSasToken), parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri)]" + } + ] + } + }, + "protectedSettings": { + "value": "[parameters('extensionCustomScriptProtectedSetting')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "condition": "[parameters('extensionDiskEncryptionConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DiskEncryption', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DiskEncryption" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'AzureDiskEncryption', 'AzureDiskEncryptionForLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'typeHandlerVersion'), parameters('extensionDiskEncryptionConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '2.2', '1.1'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDiskEncryptionConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'enableAutomaticUpgrade'), parameters('extensionDiskEncryptionConfig').enableAutomaticUpgrade, false())]" + }, + "forceUpdateTag": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'forceUpdateTag'), parameters('extensionDiskEncryptionConfig').forceUpdateTag, '1.0')]" + }, + "settings": { + "value": "[parameters('extensionDiskEncryptionConfig').settings]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9761051806804260858" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "condition": "[not(empty(parameters('backupVaultName')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Backup', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[parameters('backupVaultResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "backupResourceName": { + "value": "[format('{0}/Azure/iaasvmcontainer;iaasvmcontainerv2;{1};{2}/vm;iaasvmcontainerv2;{3};{4}', parameters('backupVaultName'), resourceGroup().name, parameters('name'), resourceGroup().name, parameters('name'))]" + }, + "protectedItemType": { + "value": "Microsoft.Compute/virtualMachines" + }, + "backupPolicyId": { + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('backupVaultName'), parameters('backupPolicyName'))]" + }, + "sourceResourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "4804590430499663077" + } + }, + "parameters": { + "backupResourceName": { + "type": "string" + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ] + }, + "backupPolicyId": { + "type": "string" + }, + "sourceResourceId": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2021-06-01", + "name": "[parameters('backupResourceName')]", + "location": "[resourceGroup().location]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('backupPolicyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "copy": { + "name": "virtualMachine_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "14627441919207189649" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the VM." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "metadata": { + "description": "The resource ID of the VM." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the VM was created in." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), '2021-07-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), '2021-07-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdWorkloadSubsId')), format('{0}', parameters('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Availability-Set-{0}', parameters('time')))]" + ] + }, + { + "copy": { + "name": "addAvdHostsToHostPool", + "count": "[length(range(0, parameters('avdDeploySessionHostsCount')))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Add-AVD-Session-Host-{0}-to-HostPool-{1}', range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "hostPoolToken": { + "value": "[parameters('hostPoolToken')]" + }, + "name": { + "value": "[format('{0}-{1}', parameters('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()])]" + }, + "hostPoolName": { + "value": "[parameters('avdHostPoolName')]" + }, + "avdAgentPackageLocation": { + "value": "[parameters('avdAgentPackageLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7262331672277958825" + } + }, + "parameters": { + "name": { + "type": "string" + }, + "location": { + "type": "string" + }, + "avdAgentPackageLocation": { + "type": "string" + }, + "hostPoolName": { + "type": "string" + }, + "systemData": { + "type": "object", + "defaultValue": {} + }, + "hostPoolToken": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/Microsoft.PowerShell.DSC', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.PowerShell", + "type": "DSC", + "typeHandlerVersion": "2.73", + "autoUpgradeMinorVersion": true, + "settings": { + "modulesUrl": "[parameters('avdAgentPackageLocation')]", + "configurationFunction": "Configuration.ps1\\AddSessionHost", + "properties": { + "hostPoolName": "[parameters('hostPoolName')]", + "registrationInfoToken": "[parameters('hostPoolToken')]", + "aadJoin": false, + "sessionHostConfigurationLastUpdateTime": "[if(contains(parameters('systemData'), 'hostpoolUpdate'), parameters('systemData').sessionHostConfigurationVersion, '')]" + } + } + } + } + ] + } + }, + "dependsOn": [ + "avdSessionHosts" + ] + }, + { + "copy": { + "name": "configureFsLogixForAvdHosts", + "count": "[length(range(0, parameters('avdDeploySessionHostsCount')))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Configure-FsLogix-for-{0}-{1}-{2}', parameters('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdWorkloadSubsId'))]", + "resourceGroup": "[format('{0}', parameters('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "name": { + "value": "[format('{0}-{1}', parameters('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()])]" + }, + "file": { + "value": "[parameters('fsLogixScript')]" + }, + "FsLogixScriptArguments": { + "value": "[parameters('FsLogixScriptArguments')]" + }, + "baseScriptUri": { + "value": "[parameters('fslogixScriptUri')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "18440939082623270082" + } + }, + "parameters": { + "name": { + "type": "string" + }, + "location": { + "type": "string" + }, + "baseScriptUri": { + "type": "string" + }, + "file": { + "type": "string" + }, + "FsLogixScriptArguments": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/configurefslogix', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Compute", + "type": "CustomScriptExtension", + "typeHandlerVersion": "1.10", + "autoUpgradeMinorVersion": true, + "settings": {}, + "protectedSettings": { + "fileUris": "[array(parameters('baseScriptUri'))]", + "commandToExecute": "[format('powershell -ExecutionPolicy Unrestricted -File {0} {1}', parameters('file'), parameters('FsLogixScriptArguments'))]" + } + } + } + ] + } + }, + "dependsOn": [ + "avdSessionHosts" + ] + } + ] + } + }, + "dependsOn": [ + "avdBaselineResourceGroups", + "[subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-HostPool-AppGroups-{0}', parameters('time')))]", + "[subscriptionResourceId('Microsoft.Resources/deployments', format('Deploy-AVD-Networking-{0}', parameters('time')))]", + "[subscriptionResourceId('Microsoft.Resources/deployments', 'Create-ManagedIdentities-RoleAssign')]" + ] + } + ] +} \ No newline at end of file diff --git a/workload/arm/deploy-custom-image.json b/workload/arm/deploy-custom-image.json new file mode 100644 index 000000000..d6034d313 --- /dev/null +++ b/workload/arm/deploy-custom-image.json @@ -0,0 +1,9192 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "4932952556543007150" + } + }, + "parameters": { + "deploymentPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. The name of the resource group to deploy" + }, + "maxLength": 4, + "minLength": 2 + }, + "avdSharedServicesLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "avdSharedServicesSubId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. AVD shared services subscription ID, multiple subscriptions scenario" + } + }, + "avdUseAvailabilityZones": { + "type": "bool", + "metadata": { + "description": "Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)" + } + }, + "aibLocation": { + "type": "string", + "defaultValue": "eastus2", + "metadata": { + "description": "Azure image builder location (Defualt: eastus2)" + }, + "allowedValues": [ + "eastus", + "eastus2", + "westcentralus", + "westus", + "westus2", + "westus3", + "southcentralus", + "northeurope", + "westeurope", + "southeastasia", + "australiasoutheast", + "australiaeast", + "uksouth", + "ukwest" + ] + }, + "createAibCustomRole": { + "type": "bool", + "metadata": { + "description": "Create custom azure image builder role" + } + }, + "avdOsImage": { + "type": "string", + "defaultValue": "win10_21h2", + "metadata": { + "description": "Required. AVD OS image source (Default: win10-21h2)" + }, + "allowedValues": [ + "win10_21h2_office", + "win10_21h2", + "win11_21h2_office", + "win11_21h2" + ] + }, + "useSharedImage": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Set to deploy image from Azure Compute Gallery" + } + }, + "createAibManagedIdentity": { + "type": "bool", + "metadata": { + "description": "Create azure image Builder managed identity" + } + }, + "existingAibManagedIdentityId": { + "type": "string", + "metadata": { + "description": "Select existing azure image Builder managed identity" + } + }, + "existingAibManagedIdentityName": { + "type": "string", + "metadata": { + "description": "Select existing azure image Builder managed identity" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "variables": { + "deploymentPrefixLowercase": "[toLower(parameters('deploymentPrefix'))]", + "avdSharedServicesLocationLowercase": "[toLower(parameters('avdSharedServicesLocation'))]", + "avdSharedResourcesRgName": "[format('rg-{0}-avd-shared-resources', variables('avdSharedServicesLocationLowercase'))]", + "imageGalleryName": "[format('avdgallery{0}', variables('avdSharedServicesLocationLowercase'))]", + "aibManagedIdentityName": "avd-uai-aib", + "deployScriptManagedIdentityName": "avd-uai-deployScript", + "imageDefinitionsTemSpecName": "[format('AVDImageDefinition_{0}', parameters('avdOsImage'))]", + "imageVmSize": "Standard_D4s_v3", + "avdOsImageDefinitions": { + "win10_21h2_office": { + "name": "Windows10_21H2_Office", + "osType": "Windows", + "osState": "Generalized", + "offer": "office-365", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win10-21h2-avd-m365", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V1" + }, + "win10_21h2": { + "name": "Windows10_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "windows-10", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win10-21h2-avd", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V1" + }, + "win11_21h2_office": { + "name": "Windows11_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "office-365", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win11-21h2-avd-m365", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V2" + }, + "win11_21h2": { + "name": "Windows11_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "windows-11", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win11-21h2-avd", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V2" + } + }, + "baseScriptUri": "https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/", + "avdSharedSResourcesStorageName": "[format('avd{0}shared', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSharedServicesLocationLowercase')))]", + "avdSharedSResourcesAibContainerName": "[format('aib-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedSResourcesScriptsContainerName": "[format('scripts-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedServicesKvName": "[format('avd-{0}-shared', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSharedServicesLocationLowercase'), parameters('avdSharedServicesSubId')))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Shared-Resources-{0}', parameters('time'))]", + "subscriptionId": "[parameters('avdSharedServicesSubId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedResourcesRgName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "6346603861226831183" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16502867888496328188" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7349811198925286397" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAibCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Azure-Image-Builder-Role-{0}', parameters('time'))]", + "subscriptionId": "[parameters('avdSharedServicesSubId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "subscriptionId": { + "value": "[parameters('avdSharedServicesSubId')]" + }, + "description": { + "value": "Azure Image Builder AVD" + }, + "roleName": { + "value": "AzureImageBuilder-AVD" + }, + "actions": { + "value": [ + "Microsoft.Authorization/*/read", + "Microsoft.Compute/images/write", + "Microsoft.Compute/images/read", + "Microsoft.Compute/images/delete", + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read", + "Microsoft.Compute/galleries/images/versions/read", + "Microsoft.Compute/galleries/images/versions/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/read", + "Microsoft.Storage/storageAccounts/blobServices/containers/write", + "Microsoft.Storage/storageAccounts/blobServices/read", + "Microsoft.ContainerInstance/containerGroups/read", + "Microsoft.ContainerInstance/containerGroups/write", + "Microsoft.ContainerInstance/containerGroups/start/action", + "Microsoft.ManagedIdentity/userAssignedIdentities/*/read", + "Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action", + "Microsoft.Authorization/*/read", + "Microsoft.Resources/deployments/*", + "Microsoft.Resources/deploymentScripts/read", + "Microsoft.Resources/deploymentScripts/write", + "Microsoft.Resources/subscriptions/resourceGroups/read", + "Microsoft.VirtualMachineImages/imageTemplates/run/action", + "Microsoft.VirtualMachineImages/imageTemplates/read", + "Microsoft.Network/virtualNetworks/read", + "Microsoft.Network/virtualNetworks/subnets/join/action" + ] + }, + "assignableScopes": { + "value": [ + "[format('/subscriptions/{0}', parameters('avdSharedServicesSubId'))]" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17958156382709624698" + } + }, + "parameters": { + "roleName": { + "type": "string", + "metadata": { + "description": "Required. Name of the custom RBAC role to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the custom RBAC role to be created." + } + }, + "actions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed actions." + } + }, + "notActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied actions." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "notDataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "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." + } + }, + "assignableScopes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Role definition assignable scopes. If not provided, will use the current scope provided." + } + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2018-01-01-preview", + "name": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "properties": { + "roleName": "[parameters('roleName')]", + "description": "[parameters('description')]", + "type": "customRole", + "permissions": [ + { + "actions": "[parameters('actions')]", + "notActions": "[parameters('notActions')]", + "dataActions": "[parameters('dataActions')]", + "notDataActions": "[parameters('notDataActions')]" + } + ], + "assignableScopes": "[if(not(empty(parameters('assignableScopes'))), parameters('assignableScopes'), array(subscription().id))]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "metadata": { + "description": "The GUID of the Role Definition" + } + }, + "scope": { + "type": "string", + "value": "[subscription().id]", + "metadata": { + "description": "The scope this Role Definition applies to" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Authorization/roleDefinitions', guid(parameters('roleName'), parameters('subscriptionId')))]", + "metadata": { + "description": "The resource ID of the Role Definition" + } + } + } + } + } + }, + { + "condition": "[parameters('createAibManagedIdentity')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('image-Builder-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('aibManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "898753467118766512" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1955613549866019244" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16170145476247528488" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "clientId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).clientId]", + "metadata": { + "description": "The client ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('deployment-Script-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('deployScriptManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "898753467118766512" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1955613549866019244" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16170145476247528488" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "clientId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).clientId]", + "metadata": { + "description": "The client ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAibManagedIdentity')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-userManagedIdentityDelay-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('AVD-userManagedIdentityDelay-{0}', parameters('time'))]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT10M" + }, + "scriptContent": { + "value": "[if(or(parameters('useSharedImage'), parameters('createAibManagedIdentity')), ' Write-Host \"Start\"\r\n Get-Date\r\n Start-Sleep -Seconds 60\r\n Write-Host \"Stop\"\r\n Get-Date\r\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "10386328014384479809" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT6H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1955613549866019244" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Azure-Image-Builder-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createAibCustomRole'), reference(subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value, subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Authorization/roleDefinitions', 'AzureImageBuilder-AVD'))]" + }, + "principalId": { + "value": "[if(parameters('createAibManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.principalId.value, parameters('existingAibManagedIdentityId'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8666590821633789861" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-userManagedIdentityDelay-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('deploy-script-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createAibCustomRole'), reference(subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value, format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830', parameters('avdSharedServicesSubId')))]" + }, + "principalId": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))).outputs.principalId.value, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8666590821633789861" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-userManagedIdentityDelay-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-Azure-Compute-Gallery-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('imageGalleryName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "galleryDescription": { + "value": "Azure Virtual Desktops Images" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8068522247412245626" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + }, + "minLength": 1 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the Azure Shared Image Gallery" + } + }, + "images": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Images to create" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/galleries", + "apiVersion": "2020-09-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "description": "[parameters('galleryDescription')]", + "identifier": {} + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + }, + { + "copy": { + "name": "gallery_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Gallery-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16453088859654942034" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + }, + { + "copy": { + "name": "galleries_images", + "count": "[length(parameters('images'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Gallery-Image-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('images')[copyIndex()].name]" + }, + "galleryName": { + "value": "[parameters('name')]" + }, + "osType": { + "value": "[if(contains(parameters('images')[copyIndex()], 'osType'), parameters('images')[copyIndex()].osType, 'Windows')]" + }, + "osState": { + "value": "[if(contains(parameters('images')[copyIndex()], 'osState'), parameters('images')[copyIndex()].osState, 'Generalized')]" + }, + "publisher": { + "value": "[if(contains(parameters('images')[copyIndex()], 'publisher'), parameters('images')[copyIndex()].publisher, 'MicrosoftWindowsServer')]" + }, + "offer": { + "value": "[if(contains(parameters('images')[copyIndex()], 'offer'), parameters('images')[copyIndex()].offer, 'WindowsServer')]" + }, + "sku": { + "value": "[if(contains(parameters('images')[copyIndex()], 'sku'), parameters('images')[copyIndex()].sku, '2019-Datacenter')]" + }, + "minRecommendedvCPUs": { + "value": "[if(contains(parameters('images')[copyIndex()], 'minRecommendedvCPUs'), parameters('images')[copyIndex()].minRecommendedvCPUs, 1)]" + }, + "maxRecommendedvCPUs": { + "value": "[if(contains(parameters('images')[copyIndex()], 'maxRecommendedvCPUs'), parameters('images')[copyIndex()].maxRecommendedvCPUs, 4)]" + }, + "minRecommendedMemory": { + "value": "[if(contains(parameters('images')[copyIndex()], 'minRecommendedMemory'), parameters('images')[copyIndex()].minRecommendedMemory, 4)]" + }, + "maxRecommendedMemory": { + "value": "[if(contains(parameters('images')[copyIndex()], 'maxRecommendedMemory'), parameters('images')[copyIndex()].maxRecommendedMemory, 16)]" + }, + "hyperVGeneration": { + "value": "[if(contains(parameters('images')[copyIndex()], 'hyperVGeneration'), parameters('images')[copyIndex()].hyperVGeneration, 'V1')]" + }, + "imageDefinitionDescription": { + "value": "[if(contains(parameters('images')[copyIndex()], 'imageDefinitionDescription'), parameters('images')[copyIndex()].imageDefinitionDescription, '')]" + }, + "eula": { + "value": "[if(contains(parameters('images')[copyIndex()], 'eula'), parameters('images')[copyIndex()].eula, '')]" + }, + "privacyStatementUri": { + "value": "[if(contains(parameters('images')[copyIndex()], 'privacyStatementUri'), parameters('images')[copyIndex()].privacyStatementUri, '')]" + }, + "releaseNoteUri": { + "value": "[if(contains(parameters('images')[copyIndex()], 'releaseNoteUri'), parameters('images')[copyIndex()].releaseNoteUri, '')]" + }, + "productName": { + "value": "[if(contains(parameters('images')[copyIndex()], 'productName'), parameters('images')[copyIndex()].productName, '')]" + }, + "planName": { + "value": "[if(contains(parameters('images')[copyIndex()], 'planName'), parameters('images')[copyIndex()].planName, '')]" + }, + "planPublisherName": { + "value": "[if(contains(parameters('images')[copyIndex()], 'planPublisherName'), parameters('images')[copyIndex()].planPublisherName, '')]" + }, + "endOfLife": { + "value": "[if(contains(parameters('images')[copyIndex()], 'endOfLife'), parameters('images')[copyIndex()].endOfLife, '')]" + }, + "excludedDiskTypes": { + "value": "[if(contains(parameters('images')[copyIndex()], 'excludedDiskTypes'), parameters('images')[copyIndex()].excludedDiskTypes, createArray())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('images')[copyIndex()], 'roleAssignments'), parameters('images')[copyIndex()].roleAssignments, createArray())]" + }, + "tags": { + "value": "[if(contains(parameters('images')[copyIndex()], 'tags'), parameters('images')[copyIndex()].tags, createObject())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2503253501666641755" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + } + }, + "osType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "WindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "2019-Datacenter", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2" + } + }, + "imageDefinitionDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of this gallery Image Definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL." + } + }, + "privacyStatementUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The privacy statement uri. Has to be a valid URL." + } + }, + "releaseNoteUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "productName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The product ID." + } + }, + "planName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The plan ID." + } + }, + "planPublisherName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The publisher ID." + } + }, + "endOfLife": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z" + } + }, + "excludedDiskTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of the excluded disk types. E.g. Standard_LRS" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2020-09-30", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]", + "description": "[parameters('imageDefinitionDescription')]", + "eula": "[parameters('eula')]", + "privacyStatementUri": "[parameters('privacyStatementUri')]", + "releaseNoteUri": "[parameters('releaseNoteUri')]", + "purchasePlan": { + "product": "[if(not(empty(parameters('productName'))), parameters('productName'), null())]", + "name": "[if(not(empty(parameters('planName'))), parameters('planName'), null())]", + "publisher": "[if(not(empty(parameters('planPublisherName'))), parameters('planPublisherName'), null())]" + }, + "endOfLifeDate": "[parameters('endOfLife')]", + "disallowed": { + "diskTypes": "[parameters('excludedDiskTypes')]" + } + } + }, + { + "copy": { + "name": "galleryImage_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17270476839903722630" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "myCustomRoleAtSub": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the image" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the image" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed image gallery" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed image gallery" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed image gallery" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "galleryName": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))).outputs.name.value, '')]" + }, + "name": { + "value": "[variables('imageDefinitionsTemSpecName')]" + }, + "osState": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osState]" + }, + "osType": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osType]" + }, + "publisher": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].publisher]" + }, + "offer": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].offer]" + }, + "sku": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].sku]" + }, + "location": { + "value": "[parameters('aibLocation')]" + }, + "hyperVGeneration": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].hyperVGeneration]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2503253501666641755" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + } + }, + "osType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "WindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "2019-Datacenter", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2" + } + }, + "imageDefinitionDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of this gallery Image Definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL." + } + }, + "privacyStatementUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The privacy statement uri. Has to be a valid URL." + } + }, + "releaseNoteUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "productName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The product ID." + } + }, + "planName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The plan ID." + } + }, + "planPublisherName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The publisher ID." + } + }, + "endOfLife": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z" + } + }, + "excludedDiskTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of the excluded disk types. E.g. Standard_LRS" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2020-09-30", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]", + "description": "[parameters('imageDefinitionDescription')]", + "eula": "[parameters('eula')]", + "privacyStatementUri": "[parameters('privacyStatementUri')]", + "releaseNoteUri": "[parameters('releaseNoteUri')]", + "purchasePlan": { + "product": "[if(not(empty(parameters('productName'))), parameters('productName'), null())]", + "name": "[if(not(empty(parameters('planName'))), parameters('planName'), null())]", + "publisher": "[if(not(empty(parameters('planPublisherName'))), parameters('planPublisherName'), null())]" + }, + "endOfLifeDate": "[parameters('endOfLife')]", + "disallowed": { + "diskTypes": "[parameters('excludedDiskTypes')]" + } + } + }, + { + "copy": { + "name": "galleryImage_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17270476839903722630" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "myCustomRoleAtSub": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the image" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the image" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Deploy-Image-Template-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('imageDefinitionsTemSpecName')]" + }, + "userMsiName": { + "value": "[if(and(parameters('createAibManagedIdentity'), parameters('useSharedImage')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.name.value, parameters('existingAibManagedIdentityName'))]" + }, + "userMsiResourceGroup": { + "value": "[if(and(parameters('createAibManagedIdentity'), parameters('useSharedImage')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.resourceGroupName.value, variables('avdSharedResourcesRgName'))]" + }, + "location": { + "value": "[parameters('aibLocation')]" + }, + "imageReplicationRegions": { + "value": "[if(equals(parameters('avdSharedServicesLocation'), parameters('aibLocation')), array(format('{0}', parameters('avdSharedServicesLocation'))), concat(array(format('{0}', parameters('aibLocation'))), array(format('{0}', parameters('avdSharedServicesLocation')))))]" + }, + "sigImageDefinitionId": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))).outputs.resourceId.value, '')]" + }, + "vmSize": { + "value": "[variables('imageVmSize')]" + }, + "customizationSteps": { + "value": [ + { + "type": "PowerShell", + "name": "OptimizeOS", + "runElevated": true, + "runAsSystem": true, + "scriptUri": "[format('{0}scripts/Optimize_OS_for_AVD.ps1', variables('baseScriptUri'))]" + }, + { + "type": "WindowsRestart", + "restartCheckCommand": "write-host \"restarting post Optimizations\"", + "restartTimeout": "10m" + }, + { + "type": "WindowsUpdate", + "searchCriteria": "IsInstalled=0", + "filters": [ + "exclude:$_.Title -like '*Preview*'", + "include:$true" + ], + "updateLimit": 40 + }, + { + "type": "PowerShell", + "name": "Sleep for a min", + "runElevated": true, + "runAsSystem": true, + "inline": [ + "Write-Host \"Sleep for a 5 min\" ", + "Start-Sleep -Seconds 300" + ] + }, + { + "type": "WindowsRestart", + "restartCheckCommand": "write-host \"restarting post Windows updates\"", + "restartTimeout": "10m" + }, + { + "type": "PowerShell", + "name": "Sleep for a min", + "runElevated": true, + "runAsSystem": true, + "inline": [ + "Write-Host \"Sleep for a min\" ", + "Start-Sleep -Seconds 60" + ] + }, + { + "type": "WindowsRestart", + "restartTimeout": "10m" + } + ] + }, + "imageSource": { + "value": { + "type": "PlatformImage", + "publisher": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].publisher]", + "offer": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].offer]", + "sku": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].sku]", + "osAccountType": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osAccountType]", + "version": "latest" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "13726005162595622237" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Image Template to be built by the Azure Image Builder service." + } + }, + "userMsiName": { + "type": "string", + "metadata": { + "description": "Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder." + } + }, + "userMsiResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the user assigned identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "buildTimeoutInMinutes": { + "type": "int", + "defaultValue": 0, + "maxValue": 960, + "minValue": 0, + "metadata": { + "description": "Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes." + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_D2s_v3", + "metadata": { + "description": "Optional. Specifies the size for the VM." + } + }, + "osDiskSizeGB": { + "type": "int", + "defaultValue": 128, + "metadata": { + "description": "Optional. Specifies the size of OS disk." + } + }, + "subnetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of an already existing subnet, e.g. '/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/'. If no value is provided, a new VNET will be created in the target Resource Group." + } + }, + "imageSource": { + "type": "object", + "metadata": { + "description": "Required. Image source definition in object format." + } + }, + "customizationSteps": { + "type": "array", + "metadata": { + "description": "Required. Customization steps to be run when building the VM image." + } + }, + "managedImageName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the managed image that will be created in the AIB resourcegroup." + } + }, + "unManagedImageName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the unmanaged image that will be created in the AIB resourcegroup." + } + }, + "sigImageDefinitionId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/." + } + }, + "imageReplicationRegions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment's location will be taken as a default value." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a unique image template name." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'." + } + } + }, + "variables": { + "managedImageName_var": "[format('{0}-{1}', parameters('managedImageName'), parameters('baseTime'))]", + "managedImageId": "[format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/images/{2}', subscription().subscriptionId, resourceGroup().name, variables('managedImageName_var'))]", + "imageReplicationRegions_var": "[if(empty(parameters('imageReplicationRegions')), array(parameters('location')), parameters('imageReplicationRegions'))]", + "managedImage": { + "type": "ManagedImage", + "imageId": "[variables('managedImageId')]", + "location": "[parameters('location')]", + "runOutputName": "[format('{0}-ManagedImage', variables('managedImageName_var'))]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + } + }, + "conditionalManagedImage": "[if(empty(parameters('managedImageName')), createArray(), array(variables('managedImage')))]", + "sharedImage": { + "type": "SharedImage", + "galleryImageId": "[parameters('sigImageDefinitionId')]", + "runOutputName": "[if(not(empty(parameters('sigImageDefinitionId'))), format('{0}-SharedImage', split(parameters('sigImageDefinitionId'), '/')[10]), 'SharedImage')]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + }, + "replicationRegions": "[variables('imageReplicationRegions_var')]" + }, + "conditionalSharedImage": "[if(empty(parameters('sigImageDefinitionId')), createArray(), array(variables('sharedImage')))]", + "unManagedImage": { + "type": "VHD", + "runOutputName": "[format('{0}-VHD', parameters('unManagedImageName'))]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + } + }, + "conditionalUnManagedImage": "[if(empty(parameters('unManagedImageName')), createArray(), array(variables('unManagedImage')))]", + "distribute": "[concat(variables('conditionalManagedImage'), variables('conditionalSharedImage'), variables('conditionalUnManagedImage'))]", + "vnetConfig": { + "subnetId": "[parameters('subnetId')]" + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.VirtualMachineImages/imageTemplates", + "apiVersion": "2020-02-14", + "name": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId(parameters('userMsiResourceGroup'), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userMsiName')))]": {} + } + }, + "properties": { + "buildTimeoutInMinutes": "[parameters('buildTimeoutInMinutes')]", + "vmProfile": { + "vmSize": "[parameters('vmSize')]", + "osDiskSizeGB": "[parameters('osDiskSizeGB')]", + "vnetConfig": "[if(not(empty(parameters('subnetId'))), variables('vnetConfig'), null())]" + }, + "source": "[parameters('imageSource')]", + "customize": "[parameters('customizationSteps')]", + "distribute": "[variables('distribute')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", + "name": "[format('{0}-{1}-lock', format('{0}-{1}', parameters('name'), parameters('baseTime')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + ] + }, + { + "copy": { + "name": "imageTemplate_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-ImageTemplate-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1117209359171295597" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the principals to assign the role to." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to." + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the role assignment." + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2020-10-01-preview", + "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(resourceId('Microsoft.VirtualMachineImages/imageTemplates', last(split(parameters('resourceId'), '/'))), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", + "metadata": { + "description": "The resource ID of the image template." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image template was deployed into." + } + }, + "name": { + "type": "string", + "value": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", + "metadata": { + "description": "The name of the image template." + } + }, + "runThisCommand": { + "type": "string", + "value": "[format('Invoke-AzResourceAction -ResourceName {0} -ResourceGroupName {1} -ResourceType Microsoft.VirtualMachineImages/imageTemplates -Action Run -Force', format('{0}-{1}', parameters('name'), parameters('baseTime')), resourceGroup().name)]", + "metadata": { + "description": "The command to run in order to trigger the image build." + } + }, + "location": { + "type": "string", + "value": "[reference(resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime'))), '2020-02-14', 'full').location]", + "metadata": { + "description": "The location the resource was deployed into." + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))]", + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Build-Image-Template-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('imageTemplateBuildName-{0}', parameters('avdOsImage'))]" + }, + "location": { + "value": "[parameters('aibLocation')]" + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT2H" + }, + "containerGroupName": { + "value": "[format('imageTemplateBuildName-{0}-aci', parameters('avdOsImage'))]" + }, + "userAssignedIdentities": { + "value": "[if(parameters('createAibManagedIdentity'), createObject(format('{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value), createObject()), createObject(format('{0}', parameters('existingAibManagedIdentityId')), createObject()))]" + }, + "arguments": { + "value": "[format('-subscriptionId ''{0}'' -resourceGroupName ''{1}'' -imageTemplateName ''{2}''', parameters('avdSharedServicesSubId'), variables('avdSharedResourcesRgName'), if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))).outputs.name.value, null()))]" + }, + "scriptContent": { + "value": "[if(parameters('useSharedImage'), ' param(\r\n [string] [Parameter(Mandatory=$true)] $resourceGroupName,\r\n [string] [Parameter(Mandatory=$true)] $imageTemplateName,\r\n [string] [Parameter(Mandatory=$true)] $subscriptionId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n Install-Module -Name Az.ImageBuilder -Force\r\n # Kick off the Azure Image Build \r\n Write-Host \"Kick off Image buld for $imageTemplateName\"\r\n Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $resourceGroupName -ResourceType \"Microsoft.VirtualMachineImages/imageTemplates\" -Action Run -Force \r\n $DeploymentScriptOutputs = @{}\r\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\r\n $status=$getStatus.LastRunStatusRunState\r\n $statusMessage=$getStatus.LastRunStatusMessage\r\n $startTime=Get-Date\r\n $reset=$startTime + (New-TimeSpan -Minutes 40)\r\n Write-Host \"Script will time out in $reset\"\r\n do {\r\n $now=Get-Date\r\n Write-Host \"Getting the current time: $now\"\r\n if (($now -eq $reset) -or ($now -gt $reset)) {\r\n break\r\n }\r\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\r\n $status=$getStatus.LastRunStatusRunState\r\n Write-Host \"Current status of the image build $imageTemplateName is: $status\"\r\n Write-Host \"Script will time out in $reset\"\r\n $DeploymentScriptOutputs=$now\r\n $DeploymentScriptOutputs=$status\r\n if ($status -eq \"Failed\") {\r\n Write-Host \"Build failed for image template: $imageTemplateName. Check the Packer logs\"\r\n $DeploymentScriptOutputs=\"Build Failed\"\r\n throw \"Build Failed\"\r\n }\r\n if (($status -eq \"Canceled\") -or ($status -eq \"Canceling\") ) {\r\n Write-Host \"User canceled the build. Delete the Image template definition: $imageTemplateName\"\r\n throw \"User canceled the build.\"\r\n }\r\n if ($status -eq \"Succeeded\") {\r\n Write-Host \"Success. Image template definition: $imageTemplateName is finished \"\r\n break\r\n }\r\n }\r\n until (($now -eq $reset) -or ($now -gt $reset))\r\n Write-Host \"Finished check for image build status at $now\"\r\n\r\n\r\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "17800535580217469804" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT1H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Shared-Services-KeyVault-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Shared-Services-KeyVault-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedServicesKvName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "enableRbacAuthorization": { + "value": false + }, + "enablePurgeProtection": { + "value": true + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7117964379708714511" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "maxLength": 24, + "metadata": { + "description": "Optional. Name of the Key Vault. If no name is provided, then unique name will be created." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of access policies object" + } + }, + "secrets": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. All secrets to create" + } + }, + "keys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. All keys to create" + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute" + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment" + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios." + } + }, + "enableSoftDelete": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "defaultValue": 90, + "metadata": { + "description": "Optional. softDelete data retention days. It accepts >=7 and <=90." + } + }, + "enableRbacAuthorization": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC." + } + }, + "createMode": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "vaultSku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault" + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "enabled", + "allowedValues": [ + "enabled", + "disabled" + ], + "metadata": { + "description": "Optional. Property to specify whether the vault will accept traffic from public internet. If set to \"disabled\" all traffic except private endpoint traffic and that that originates from trusted services will be blocked. This will override the set firewall rules, meaning that even if the firewall rules are present we will not honor the rules." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. " + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "AuditEvent", + "AzurePolicyEvaluationDetails" + ], + "allowedValues": [ + "AuditEvent", + "AzurePolicyEvaluationDetails" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ], + "maxNameLength": 24, + "uniquenameUntrim": "[uniqueString(format('Key Vault{0}', parameters('baseTime')))]", + "uniquename": "[if(greater(length(variables('uniquenameUntrim')), variables('maxNameLength')), substring(variables('uniquenameUntrim'), 0, variables('maxNameLength')), variables('uniquenameUntrim'))]", + "name_var": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniquename'))]", + "networkAcls_var": { + "bypass": "[if(not(empty(parameters('networkAcls'))), parameters('networkAcls').bypass, null())]", + "defaultAction": "[if(not(empty(parameters('networkAcls'))), parameters('networkAcls').defaultAction, null())]", + "virtualNetworkRules": "[if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'virtualNetworkRules')), parameters('networkAcls').virtualNetworkRules, createArray())]", + "ipRules": "[if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'ipRules')), parameters('networkAcls').ipRules, createArray())]" + }, + "secretList": "[if(not(empty(parameters('secrets'))), parameters('secrets').secureList, createArray())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2021-11-01-preview", + "name": "[variables('name_var')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "enabledForDeployment": "[parameters('enableVaultForDeployment')]", + "enabledForTemplateDeployment": "[parameters('enableVaultForTemplateDeployment')]", + "enabledForDiskEncryption": "[parameters('enableVaultForDiskEncryption')]", + "enableSoftDelete": "[parameters('enableSoftDelete')]", + "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]", + "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]", + "createMode": "[parameters('createMode')]", + "enablePurgeProtection": "[if(parameters('enablePurgeProtection'), parameters('enablePurgeProtection'), null())]", + "tenantId": "[subscription().tenantId]", + "accessPolicies": "[variables('formattedAccessPolicies')]", + "sku": { + "name": "[parameters('vaultSku')]", + "family": "A" + }, + "networkAcls": "[if(not(empty(parameters('networkAcls'))), variables('networkAcls_var'), null())]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-{1}-lock', variables('name_var'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "accessPolicies": { + "value": "[variables('formattedAccessPolicies')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16492524556919253664" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "defaultValue": "add", + "metadata": { + "description": "Optional. The access policy deployment" + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2021-06-01-preview", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the access policies assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the access policies assignment" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_secrets", + "count": "[length(variables('secretList'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('secretList')[copyIndex()].name]" + }, + "value": { + "value": "[variables('secretList')[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesEnabled'), variables('secretList')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesExp'), variables('secretList')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesNbf'), variables('secretList')[copyIndex()].attributesNbf, -1)]" + }, + "contentType": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'contentType'), variables('secretList')[copyIndex()].contentType, '')]" + }, + "tags": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'tags'), variables('secretList')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'roleAssignments'), variables('secretList')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9855184563194001290" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "secureString", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "value": "[parameters('value')]" + } + }, + { + "copy": { + "name": "secret_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "12822591518009644118" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the secret." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the secret." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the secret was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_keys", + "count": "[length(parameters('keys'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('keys')[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesEnabled'), parameters('keys')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesExp'), parameters('keys')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesNbf'), parameters('keys')[copyIndex()].attributesNbf, -1)]" + }, + "curveName": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'curveName'), parameters('keys')[copyIndex()].curveName, 'P-256')]" + }, + "keyOps": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keyOps'), parameters('keys')[copyIndex()].keyOps, createArray())]" + }, + "keySize": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keySize'), parameters('keys')[copyIndex()].keySize, -1)]" + }, + "kty": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'kty'), parameters('keys')[copyIndex()].kty, 'EC')]" + }, + "tags": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'tags'), parameters('keys')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'roleAssignments'), parameters('keys')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "9202505798573795419" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "curveName": { + "type": "string", + "defaultValue": "P-256", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "metadata": { + "description": "Optional. The elliptic curve name." + } + }, + "keyOps": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation" + } + }, + "keySize": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA." + } + }, + "kty": { + "type": "string", + "defaultValue": "EC", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "metadata": { + "description": "Optional. The type of the key." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "curveName": "[parameters('curveName')]", + "keyOps": "[parameters('keyOps')]", + "keySize": "[if(not(equals(parameters('keySize'), -1)), parameters('keySize'), null())]", + "kty": "[parameters('kty')]" + } + }, + { + "copy": { + "name": "key_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8663685790625721754" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the key." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the key." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "14496837389589298146" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + }, + { + "condition": "[not(empty(variables('privateEndpoint_var').privateDnsZoneResourceIds))]", + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/default', variables('privateEndpoint_var').name)]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds)))]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15956299923651638071" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]", + "metadata": { + "description": "The resource ID of the key vault." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key vault was created in." + } + }, + "name": { + "type": "string", + "value": "[variables('name_var')]", + "metadata": { + "description": "The name of the key vault." + } + }, + "uri": { + "type": "string", + "value": "[reference(resourceId('Microsoft.KeyVault/vaults', variables('name_var'))).vaultUri]", + "metadata": { + "description": "The URI of the key vault." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Shared-Services-Storage-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedSResourcesStorageName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "storageAccountSku": { + "value": "[if(parameters('avdUseAvailabilityZones'), 'Standard_ZRS', 'Standard_LRS')]" + }, + "storageAccountKind": { + "value": "StorageV2" + }, + "blobServices": { + "value": { + "containers": [ + { + "name": "[variables('avdSharedSResourcesAibContainerName')]", + "publicAccess": "None" + }, + { + "name": "[variables('avdSharedSResourcesScriptsContainerName')]", + "publicAccess": "None" + } + ] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2820787175439416263" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Storage Account. Autogenerated with a unique string if not provided." + }, + "maxLength": 24 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "storageAccountKind": { + "type": "string", + "defaultValue": "StorageV2", + "metadata": { + "description": "Optional. Type of Storage Account to create." + }, + "allowedValues": [ + "Storage", + "StorageV2", + "BlobStorage", + "FileStorage", + "BlockBlobStorage" + ] + }, + "storageAccountSku": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage Account Sku Name." + }, + "allowedValues": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS", + "Premium_ZRS", + "Standard_GZRS", + "Standard_RAGZRS" + ] + }, + "storageAccountAccessTier": { + "type": "string", + "defaultValue": "Hot", + "metadata": { + "description": "Optional. Storage Account Access Tier." + }, + "allowedValues": [ + "Hot", + "Cool" + ] + }, + "azureFilesIdentityBasedAuthentication": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Provides the identity based authentication settings for Azure Files." + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "managementPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Storage Account ManagementPolicies Rules." + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true." + } + }, + "blobServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Blob service and containers to deploy" + } + }, + "fileServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. File service and shares to deploy" + } + }, + "queueServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Queue service and queues to create." + } + }, + "tableServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Table service and tables to create." + } + }, + "allowBlobPublicAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "TLS1_2", + "metadata": { + "description": "Optional. Set the minimum TLS version on request to storage." + }, + "allowedValues": [ + "TLS1_0", + "TLS1_1", + "TLS1_2" + ] + }, + "enableHierarchicalNamespace": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If true, enables Hierarchical Namespace for the storage account" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "basetime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Enabled", + "metadata": { + "description": "Optional. Enable or disallow public network access to Storage Account.." + }, + "allowedValues": [ + "Enabled", + "Disabled" + ] + }, + "supportsHttpsTrafficOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Allows HTTPS traffic only to storage service if sets to true." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "maxNameLength": 24, + "uniqueStorageNameUntrim": "[format('{0}', uniqueString(format('Storage Account{0}', parameters('basetime'))))]", + "uniqueStorageName": "[if(greater(length(variables('uniqueStorageNameUntrim')), variables('maxNameLength')), substring(variables('uniqueStorageNameUntrim'), 0, variables('maxNameLength')), variables('uniqueStorageNameUntrim'))]", + "supportsBlobService": "[or(or(or(equals(parameters('storageAccountKind'), 'BlockBlobStorage'), equals(parameters('storageAccountKind'), 'BlobStorage')), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage'))]", + "supportsFileService": "[or(or(equals(parameters('storageAccountKind'), 'FileStorage'), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage'))]", + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2021-08-01", + "name": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]", + "location": "[parameters('location')]", + "kind": "[parameters('storageAccountKind')]", + "sku": { + "name": "[parameters('storageAccountSku')]" + }, + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "properties": { + "encryption": { + "keySource": "Microsoft.Storage", + "services": { + "blob": "[if(variables('supportsBlobService'), createObject('enabled', true()), null())]", + "file": "[if(variables('supportsFileService'), createObject('enabled', true()), null())]" + }, + "requireInfrastructureEncryption": "[if(not(equals(parameters('storageAccountKind'), 'Storage')), parameters('requireInfrastructureEncryption'), null())]" + }, + "accessTier": "[if(not(equals(parameters('storageAccountKind'), 'Storage')), parameters('storageAccountAccessTier'), null())]", + "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]", + "isHnsEnabled": "[if(parameters('enableHierarchicalNamespace'), parameters('enableHierarchicalNamespace'), null())]", + "minimumTlsVersion": "[parameters('minimumTlsVersion')]", + "networkAcls": "[if(not(empty(parameters('networkAcls'))), createObject('bypass', if(not(empty(parameters('networkAcls'))), parameters('networkAcls').bypass, null()), 'defaultAction', if(not(empty(parameters('networkAcls'))), parameters('networkAcls').defaultAction, null()), 'virtualNetworkRules', if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'virtualNetworkRules')), parameters('networkAcls').virtualNetworkRules, createArray()), 'ipRules', if(and(not(empty(parameters('networkAcls'))), contains(parameters('networkAcls'), 'ipRules')), parameters('networkAcls').ipRules, createArray())), null())]", + "allowBlobPublicAccess": "[parameters('allowBlobPublicAccess')]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "azureFilesIdentityBasedAuthentication": "[if(not(empty(parameters('azureFilesIdentityBasedAuthentication'))), parameters('azureFilesIdentityBasedAuthentication'), null())]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]", + "name": "[format('{0}-{1}-lock', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "copy": { + "name": "storageAccount_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16610301563380405946" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('privateEndpoints')))]", + "copy": { + "name": "storageAccount_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-PrivateEndpoints-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(not(empty(parameters('privateEndpoints'))), reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location, 'dummy')]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "1106636052820512350" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/{1}', variables('privateEndpoint_var').name, 'default')]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(variables('privateEndpoint_var').privateDnsZoneResourceIds)]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('managementPolicyRules')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-ManagementPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "rules": { + "value": "[parameters('managementPolicyRules')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3253774105655355109" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the storage container to deploy" + } + }, + "rules": { + "type": "array", + "metadata": { + "description": "Required. The Storage Account ManagementPolicies Rules" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('rules')))]", + "type": "Microsoft.Storage/storageAccounts/managementPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "policy": { + "rules": "[parameters('rules')]" + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The resource ID of the deployed management policy" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed management policy" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed management policy" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('blobServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-BlobServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "containers": { + "value": "[if(contains(parameters('blobServices'), 'containers'), parameters('blobServices').containers, createArray())]" + }, + "automaticSnapshotPolicyEnabled": { + "value": "[if(contains(parameters('blobServices'), 'automaticSnapshotPolicyEnabled'), parameters('blobServices').automaticSnapshotPolicyEnabled, false())]" + }, + "deleteRetentionPolicy": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicy'), parameters('blobServices').deleteRetentionPolicy, true())]" + }, + "deleteRetentionPolicyDays": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicyDays'), parameters('blobServices').deleteRetentionPolicyDays, 7)]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogsRetentionInDays'), parameters('blobServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticStorageAccountId'), parameters('blobServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('blobServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubName'), parameters('blobServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogCategoriesToEnable'), parameters('blobServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticMetricsToEnable'), parameters('blobServices').diagnosticMetricsToEnable, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticWorkspaceId'), parameters('blobServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "5769438066360147349" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the blob service" + } + }, + "deleteRetentionPolicy": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service." + } + }, + "deleteRetentionPolicyDays": { + "type": "int", + "defaultValue": 7, + "metadata": { + "description": "Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365." + } + }, + "automaticSnapshotPolicyEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Automatic Snapshot is enabled if set to true." + } + }, + "containers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Blob containers to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "deleteRetentionPolicy": { + "enabled": "[parameters('deleteRetentionPolicy')]", + "days": "[parameters('deleteRetentionPolicyDays')]" + }, + "automaticSnapshotPolicyEnabled": "[parameters('automaticSnapshotPolicyEnabled')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "blobServices_container", + "count": "[length(parameters('containers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Container-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('containers')[copyIndex()].name]" + }, + "publicAccess": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'publicAccess'), parameters('containers')[copyIndex()].publicAccess, 'None')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'roleAssignments'), parameters('containers')[copyIndex()].roleAssignments, createArray())]" + }, + "immutabilityPolicyProperties": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'immutabilityPolicyProperties'), parameters('containers')[copyIndex()].immutabilityPolicyProperties, createObject())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "7149162740350746791" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage container to deploy" + } + }, + "immutabilityPolicyName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "publicAccess": { + "type": "string", + "defaultValue": "None", + "metadata": { + "description": "Optional. Specifies whether data in the container may be accessed publicly and the level of access." + }, + "allowedValues": [ + "Container", + "Blob", + "None" + ] + }, + "immutabilityPolicyProperties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Configure immutability policy." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "properties": { + "publicAccess": "[parameters('publicAccess')]" + } + }, + { + "condition": "[not(empty(parameters('immutabilityPolicyProperties')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[parameters('immutabilityPolicyName')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('blobServicesName')]" + }, + "containerName": { + "value": "[parameters('name')]" + }, + "immutabilityPeriodSinceCreationInDays": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'immutabilityPeriodSinceCreationInDays'), parameters('immutabilityPolicyProperties').immutabilityPeriodSinceCreationInDays, 365)]" + }, + "allowProtectedAppendWrites": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'allowProtectedAppendWrites'), parameters('immutabilityPolicyProperties').allowProtectedAppendWrites, true())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "12805627095883262775" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "containerName": { + "type": "string", + "metadata": { + "description": "Required. Name of the container to apply the policy to" + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "immutabilityPeriodSinceCreationInDays": { + "type": "int", + "defaultValue": 365, + "metadata": { + "description": "Optional. The immutability period for the blobs in the container since the policy creation, in days." + } + }, + "allowProtectedAppendWrites": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "properties": { + "immutabilityPeriodSinceCreationInDays": "[parameters('immutabilityPeriodSinceCreationInDays')]", + "allowProtectedAppendWrites": "[parameters('allowProtectedAppendWrites')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed immutability policy." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed immutability policy." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed immutability policy." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "container_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2389940191716042805" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}/containers/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed container" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed container" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed container" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed blob service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed blob service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the deployed blob service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('fileServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-FileServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogsRetentionInDays'), parameters('fileServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticStorageAccountId'), parameters('fileServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('fileServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubName'), parameters('fileServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogCategoriesToEnable'), parameters('fileServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticMetricsToEnable'), parameters('fileServices').diagnosticMetricsToEnable, createArray())]" + }, + "protocolSettings": { + "value": "[if(contains(parameters('fileServices'), 'protocolSettings'), parameters('fileServices').protocolSettings, createObject())]" + }, + "shareDeleteRetentionPolicy": { + "value": "[if(contains(parameters('fileServices'), 'shareDeleteRetentionPolicy'), parameters('fileServices').shareDeleteRetentionPolicy, createObject('enabled', true(), 'days', 7))]" + }, + "shares": { + "value": "[if(contains(parameters('fileServices'), 'shares'), parameters('fileServices').shares, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticWorkspaceId'), parameters('fileServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15400523973338909377" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "protocolSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Protocol settings for file service" + } + }, + "shareDeleteRetentionPolicy": { + "type": "object", + "defaultValue": { + "enabled": true, + "days": 7 + }, + "metadata": { + "description": "Optional. The service properties for soft delete." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "shares": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. File shares to create." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "protocolSettings": "[parameters('protocolSettings')]", + "shareDeleteRetentionPolicy": "[parameters('shareDeleteRetentionPolicy')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "fileServices_shares", + "count": "[length(parameters('shares'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-shares-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "fileServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('shares')[copyIndex()].name]" + }, + "enabledProtocols": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'enabledProtocols'), parameters('shares')[copyIndex()].enabledProtocols, 'SMB')]" + }, + "rootSquash": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'rootSquash'), parameters('shares')[copyIndex()].rootSquash, 'NoRootSquash')]" + }, + "sharedQuota": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'sharedQuota'), parameters('shares')[copyIndex()].sharedQuota, 5120)]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'roleAssignments'), parameters('shares')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "8012908004388630919" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "fileServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the file share to create" + } + }, + "sharedQuota": { + "type": "int", + "defaultValue": 5120, + "metadata": { + "description": "Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400." + } + }, + "enabledProtocols": { + "type": "string", + "defaultValue": "SMB", + "metadata": { + "description": "Optional. The authentication protocol that is used for the file share. Can only be specified when creating a share." + }, + "allowedValues": [ + "NFS", + "SMB" + ] + }, + "rootSquash": { + "type": "string", + "defaultValue": "NoRootSquash", + "metadata": { + "description": "Optional. Permissions for NFS file shares are enforced by the client OS rather than the Azure Files service. Toggling the root squash behavior reduces the rights of the root user for NFS shares." + }, + "allowedValues": [ + "AllSquash", + "NoRootSquash", + "RootSquash" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/fileServices/shares", + "apiVersion": "2021-08-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "properties": { + "shareQuota": "[parameters('sharedQuota')]", + "rootSquash": "[if(equals(parameters('enabledProtocols'), 'NFS'), parameters('rootSquash'), null())]", + "enabledProtocols": "[parameters('enabledProtocols')]" + } + }, + { + "copy": { + "name": "fileShare_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "2512438268213117259" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}/shares/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('queueServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-QueueServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogsRetentionInDays'), parameters('queueServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticStorageAccountId'), parameters('queueServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('queueServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubName'), parameters('queueServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogCategoriesToEnable'), parameters('queueServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticMetricsToEnable'), parameters('queueServices').diagnosticMetricsToEnable, createArray())]" + }, + "queues": { + "value": "[if(contains(parameters('queueServices'), 'queues'), parameters('queueServices').queues, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticWorkspaceId'), parameters('queueServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "15042600590518287455" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "queues": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Queues to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/queueServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "queueServices_queues", + "count": "[length(parameters('queues'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Queue-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "queueServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('queues')[copyIndex()].name]" + }, + "metadata": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'metadata'), parameters('queues')[copyIndex()].metadata, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'roleAssignments'), parameters('queues')[copyIndex()].roleAssignments, createArray())]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "5113461039331916331" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "queueServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage queue to deploy" + } + }, + "metadata": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Required. A name-value pair that represents queue metadata." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/queueServices/queues", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]" + } + }, + { + "copy": { + "name": "queue_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), parameters('roleAssignments')[copyIndex()].description, '')]" + }, + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "principalType": { + "value": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), parameters('roleAssignments')[copyIndex()].principalType, '')]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "11014868406062922847" + } + }, + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the prinicpals to assign to role to" + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead" + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Dsms Role (deprecated)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b')]", + "Dsms Role (do not use)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f')]", + "GenevaWarmPathResourceContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}/queues/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed queue" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed queue" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed queue" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + }, + { + "condition": "[not(empty(parameters('tableServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-TableServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogsRetentionInDays'), parameters('tableServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticStorageAccountId'), parameters('tableServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('tableServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubName'), parameters('tableServices').diagnosticEventHubName, '')]" + }, + "diagnosticLogCategoriesToEnable": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogCategoriesToEnable'), parameters('tableServices').diagnosticLogCategoriesToEnable, createArray())]" + }, + "diagnosticMetricsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticMetricsToEnable'), parameters('tableServices').diagnosticMetricsToEnable, createArray())]" + }, + "tables": { + "value": "[if(contains(parameters('tableServices'), 'tables'), parameters('tableServices').tables, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticWorkspaceId'), parameters('tableServices').diagnosticWorkspaceId, '')]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "16674693318462147203" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. tables to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + }, + "diagnosticLogCategoriesToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "diagnosticMetricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "diagnosticSettingsName": { + "type": "string", + "defaultValue": "[format('{0}-diagnosticSettings', parameters('name'))]", + "metadata": { + "description": "Optional. The name of the diagnostic setting, if deployed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('diagnosticLogCategoriesToEnable'))]", + "input": { + "category": "[parameters('diagnosticLogCategoriesToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('diagnosticMetricsToEnable'))]", + "input": { + "category": "[parameters('diagnosticMetricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/tableServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/tableServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[parameters('diagnosticSettingsName')]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "tableServices_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Table-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "tableServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()]]" + }, + "enableDefaultTelemetry": { + "value": "[parameters('enableDefaultTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.5.6.12127", + "templateHash": "3122726620958778940" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "tableServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via the Customer Usage Attribution ID (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/tableServices/tables", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]" + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices/tables', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed table service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed table service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed table service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName')))]", + "metadata": { + "description": "The resource ID of the deployed storage account" + } + }, + "name": { + "type": "string", + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))]", + "metadata": { + "description": "The name of the deployed storage account" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed storage account" + } + }, + "primaryBlobEndpoint": { + "type": "string", + "value": "[if(and(not(empty(parameters('blobServices'))), contains(parameters('blobServices'), 'containers')), reference(format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))), '2019-04-01').primaryEndpoints.blob, '')]", + "metadata": { + "description": "The primary blob endpoint reference if blob services are deployed." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))), '2021-08-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStorageName'))), '2021-08-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + } + ] +} \ No newline at end of file diff --git a/workload/arm/deploy-customImage.json b/workload/arm/deploy-customImage.json new file mode 100644 index 000000000..cda8325ca --- /dev/null +++ b/workload/arm/deploy-customImage.json @@ -0,0 +1,8714 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "8297409346343929460" + } + }, + "parameters": { + "deploymentPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. The name of the resource group to deploy" + }, + "maxLength": 4, + "minLength": 2 + }, + "avdSharedServicesLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "avdSharedServicesSubId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. AVD shared services subscription ID, multiple subscriptions scenario" + } + }, + "avdUseAvailabilityZones": { + "type": "bool", + "metadata": { + "description": "Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)" + } + }, + "aiblocation": { + "type": "string", + "defaultValue": "eastus2", + "metadata": { + "description": "Azure image builder location (Defualt: eastus2)" + }, + "allowedValues": [ + "eastus", + "eastus2", + "westcentralus", + "westus", + "westus2", + "westus3", + "southcentralus", + "northeurope", + "westeurope", + "southeastasia", + "australiasoutheast", + "australiaeast", + "uksouth", + "ukwest" + ] + }, + "createAibCustomRole": { + "type": "bool", + "metadata": { + "description": "Create custom azure image builder role" + } + }, + "avdOsImage": { + "type": "string", + "defaultValue": "win10_21h2", + "metadata": { + "description": "Required. AVD OS image source (Default: win10-21h2)" + }, + "allowedValues": [ + "win10_21h2_office", + "win10_21h2", + "win11_21h2_office", + "win11_21h2" + ] + }, + "useSharedImage": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Set to deploy image from Azure Compute Gallery" + } + }, + "createAibManagedIdentity": { + "type": "bool", + "metadata": { + "description": "Create azure image Builder managed identity" + } + }, + "existingAibManagedIdentityId": { + "type": "string", + "metadata": { + "description": "Select existing azure image Builder managed identity" + } + }, + "existingAibManagedIdentityName": { + "type": "string", + "metadata": { + "description": "Select existing azure image Builder managed identity" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "variables": { + "deploymentPrefixLowercase": "[toLower(parameters('deploymentPrefix'))]", + "avdSharedServicesLocationLowercase": "[toLower(parameters('avdSharedServicesLocation'))]", + "avdSharedResourcesRgName": "[format('rg-{0}-avd-shared-resources', variables('avdSharedServicesLocationLowercase'))]", + "imageGalleryName": "[format('avdgallery{0}', variables('avdSharedServicesLocationLowercase'))]", + "aibManagedIdentityName": "avd-uai-aib", + "deployScriptManagedIdentityName": "avd-uai-deployScript", + "imageDefinitionsTemSpecName": "[format('AVDImageDefinition_{0}', parameters('avdOsImage'))]", + "imageVmSize": "Standard_D4s_v3", + "avdOsImageDefinitions": { + "win10_21h2_office": { + "name": "Windows10_21H2_Office", + "osType": "Windows", + "osState": "Generalized", + "offer": "office-365", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win10-21h2-avd-m365", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V1" + }, + "win10_21h2": { + "name": "Windows10_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "windows-10", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win10-21h2-avd", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V1" + }, + "win11_21h2_office": { + "name": "Windows11_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "office-365", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win11-21h2-avd-m365", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V2" + }, + "win11_21h2": { + "name": "Windows11_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "windows-11", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win11-21h2-avd", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V2" + } + }, + "baseScriptUri": "https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/", + "avdSharedSResourcesStorageName": "[format('avd{0}shared', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSharedServicesLocationLowercase')))]", + "avdSharedSResourcesAibContainerName": "[format('aib-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedSResourcesScriptsContainerName": "[format('scripts-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedServicesKvName": "[format('avd-{0}-shared', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSharedServicesLocationLowercase')))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Shared-Resources-{0}', parameters('time'))]", + "subscriptionId": "[parameters('avdSharedServicesSubId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedResourcesRgName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "15305484723524009410" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "4530194098204811454" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "4544010209512842630" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAibCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Azure-Image-Builder-Role-{0}', parameters('time'))]", + "subscriptionId": "[parameters('avdSharedServicesSubId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "subscriptionId": { + "value": "[parameters('avdSharedServicesSubId')]" + }, + "description": { + "value": "Azure Image Builder AVD" + }, + "roleName": { + "value": "AzureImageBuilder-AVD" + }, + "actions": { + "value": [ + "Microsoft.Authorization/*/read", + "Microsoft.Compute/images/write", + "Microsoft.Compute/images/read", + "Microsoft.Compute/images/delete", + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read", + "Microsoft.Compute/galleries/images/versions/read", + "Microsoft.Compute/galleries/images/versions/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/read", + "Microsoft.Storage/storageAccounts/blobServices/containers/write", + "Microsoft.Storage/storageAccounts/blobServices/read", + "Microsoft.ContainerInstance/containerGroups/read", + "Microsoft.ContainerInstance/containerGroups/write", + "Microsoft.ContainerInstance/containerGroups/start/action", + "Microsoft.ManagedIdentity/userAssignedIdentities/*/read", + "Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action", + "Microsoft.Authorization/*/read", + "Microsoft.Resources/deployments/*", + "Microsoft.Resources/deploymentScripts/read", + "Microsoft.Resources/deploymentScripts/write", + "Microsoft.Resources/subscriptions/resourceGroups/read", + "Microsoft.VirtualMachineImages/imageTemplates/run/action", + "Microsoft.VirtualMachineImages/imageTemplates/read", + "Microsoft.Network/virtualNetworks/read", + "Microsoft.Network/virtualNetworks/subnets/join/action" + ] + }, + "assignableScopes": { + "value": [ + "[format('/subscriptions/{0}', parameters('avdSharedServicesSubId'))]" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "11123573274510279811" + } + }, + "parameters": { + "roleName": { + "type": "string", + "metadata": { + "description": "Required. Name of the custom RBAC role to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the custom RBAC role to be created." + } + }, + "actions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed actions." + } + }, + "notActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied actions." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "notDataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "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." + } + }, + "assignableScopes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Role definition assignable scopes. If not provided, will use the current scope provided." + } + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2018-01-01-preview", + "name": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "properties": { + "roleName": "[parameters('roleName')]", + "description": "[parameters('description')]", + "type": "customRole", + "permissions": [ + { + "actions": "[parameters('actions')]", + "notActions": "[parameters('notActions')]", + "dataActions": "[parameters('dataActions')]", + "notDataActions": "[parameters('notDataActions')]" + } + ], + "assignableScopes": "[if(not(empty(parameters('assignableScopes'))), parameters('assignableScopes'), array(subscription().id))]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "metadata": { + "description": "The GUID of the Role Definition" + } + }, + "scope": { + "type": "string", + "value": "[subscription().id]", + "metadata": { + "description": "The scope this Role Definition applies to" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Authorization/roleDefinitions', guid(parameters('roleName'), parameters('subscriptionId')))]", + "metadata": { + "description": "The resource ID of the Role Definition" + } + } + } + } + } + }, + { + "condition": "[parameters('createAibManagedIdentity')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('image-Builder-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('aibManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7713578982536763065" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "13906713308875706934" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "clientId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).clientId]", + "metadata": { + "description": "The client ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('deployment-Script-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('deployScriptManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7713578982536763065" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "13906713308875706934" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "clientId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).clientId]", + "metadata": { + "description": "The client ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAibManagedIdentity')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-userManagedIdentityDelay-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('AVD-userManagedIdentityDelay-{0}', parameters('time'))]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT10M" + }, + "scriptContent": { + "value": "[if(or(parameters('useSharedImage'), parameters('createAibManagedIdentity')), ' Write-Host \"Start\"\n Get-Date\n Start-Sleep -Seconds 60\n Write-Host \"Stop\"\n Get-Date\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "6451386248046840370" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT6H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Azure-Image-Builder-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createAibCustomRole'), reference(subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value, subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Authorization/roleDefinitions', 'AzureImageBuilder-AVD'))]" + }, + "principalId": { + "value": "[if(parameters('createAibManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.principalId.value, parameters('existingAibManagedIdentityId'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "1675402332512052774" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-userManagedIdentityDelay-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('deploy-script-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createAibCustomRole'), reference(subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value, format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830', parameters('avdSharedServicesSubId')))]" + }, + "principalId": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))).outputs.principalId.value, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "1675402332512052774" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-userManagedIdentityDelay-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-Azure-Compute-Gallery-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('imageGalleryName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "galleryDescription": { + "value": "Azure Virtual Desktops Images" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "2035008738549344338" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + }, + "minLength": 1 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the Azure Shared Image Gallery" + } + }, + "images": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Images to create" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/galleries", + "apiVersion": "2020-09-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "description": "[parameters('galleryDescription')]", + "identifier": {} + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "gallery_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Gallery-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "17800194225528593199" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + }, + { + "copy": { + "name": "galleries_images", + "count": "[length(parameters('images'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Gallery-Image-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('images')[copyIndex()].name]" + }, + "galleryName": { + "value": "[parameters('name')]" + }, + "osType": { + "value": "[if(contains(parameters('images')[copyIndex()], 'osType'), parameters('images')[copyIndex()].osType, 'Windows')]" + }, + "osState": { + "value": "[if(contains(parameters('images')[copyIndex()], 'osState'), parameters('images')[copyIndex()].osState, 'Generalized')]" + }, + "publisher": { + "value": "[if(contains(parameters('images')[copyIndex()], 'publisher'), parameters('images')[copyIndex()].publisher, 'MicrosoftWindowsServer')]" + }, + "offer": { + "value": "[if(contains(parameters('images')[copyIndex()], 'offer'), parameters('images')[copyIndex()].offer, 'WindowsServer')]" + }, + "sku": { + "value": "[if(contains(parameters('images')[copyIndex()], 'sku'), parameters('images')[copyIndex()].sku, '2019-Datacenter')]" + }, + "minRecommendedvCPUs": { + "value": "[if(contains(parameters('images')[copyIndex()], 'minRecommendedvCPUs'), parameters('images')[copyIndex()].minRecommendedvCPUs, 1)]" + }, + "maxRecommendedvCPUs": { + "value": "[if(contains(parameters('images')[copyIndex()], 'maxRecommendedvCPUs'), parameters('images')[copyIndex()].maxRecommendedvCPUs, 4)]" + }, + "minRecommendedMemory": { + "value": "[if(contains(parameters('images')[copyIndex()], 'minRecommendedMemory'), parameters('images')[copyIndex()].minRecommendedMemory, 4)]" + }, + "maxRecommendedMemory": { + "value": "[if(contains(parameters('images')[copyIndex()], 'maxRecommendedMemory'), parameters('images')[copyIndex()].maxRecommendedMemory, 16)]" + }, + "hyperVGeneration": { + "value": "[if(contains(parameters('images')[copyIndex()], 'hyperVGeneration'), parameters('images')[copyIndex()].hyperVGeneration, 'V1')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('images')[copyIndex()], 'roleAssignments'), parameters('images')[copyIndex()].roleAssignments, createArray())]" + }, + "tags": { + "value": "[if(contains(parameters('images')[copyIndex()], 'tags'), parameters('images')[copyIndex()].tags, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5163035773520477905" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + } + }, + "osType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "WindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "2019-Datacenter", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2020-09-30", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "galleryImage_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5829896798084043001" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "myCustomRoleAtSub": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the image" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the image" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed image gallery" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed image gallery" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed image gallery" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "galleryName": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))).outputs.name.value, '')]" + }, + "name": { + "value": "[variables('imageDefinitionsTemSpecName')]" + }, + "osState": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osState]" + }, + "osType": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osType]" + }, + "publisher": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].publisher]" + }, + "offer": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].offer]" + }, + "sku": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].sku]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "hyperVGeneration": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].hyperVGeneration]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5163035773520477905" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + } + }, + "osType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "WindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "2019-Datacenter", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2020-09-30", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "galleryImage_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5829896798084043001" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "myCustomRoleAtSub": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the image" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the image" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Deploy-Image-Template-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('imageDefinitionsTemSpecName')]" + }, + "userMsiName": { + "value": "[if(and(parameters('createAibManagedIdentity'), parameters('useSharedImage')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.name.value, parameters('existingAibManagedIdentityName'))]" + }, + "userMsiResourceGroup": { + "value": "[if(and(parameters('createAibManagedIdentity'), parameters('useSharedImage')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.resourceGroupName.value, variables('avdSharedResourcesRgName'))]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "imageReplicationRegions": { + "value": "[if(equals(parameters('avdSharedServicesLocation'), parameters('aiblocation')), array(format('{0}', parameters('avdSharedServicesLocation'))), concat(array(format('{0}', parameters('aiblocation'))), array(format('{0}', parameters('avdSharedServicesLocation')))))]" + }, + "sigImageDefinitionId": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))).outputs.resourceId.value, '')]" + }, + "vmSize": { + "value": "[variables('imageVmSize')]" + }, + "customizationSteps": { + "value": [ + { + "type": "PowerShell", + "name": "OptimizeOS", + "runElevated": true, + "runAsSystem": true, + "scriptUri": "[format('{0}scripts/Optimize_OS_for_AVD.ps1', variables('baseScriptUri'))]" + }, + { + "type": "WindowsRestart", + "restartCheckCommand": "write-host \"restarting post Optimizations\"", + "restartTimeout": "10m" + }, + { + "type": "WindowsUpdate", + "searchCriteria": "IsInstalled=0", + "filters": [ + "exclude:$_.Title -like '*Preview*'", + "include:$true" + ], + "updateLimit": 40 + }, + { + "type": "PowerShell", + "name": "Sleep for a min", + "runElevated": true, + "runAsSystem": true, + "inline": [ + "Write-Host \"Sleep for a 5 min\" ", + "Start-Sleep -Seconds 300" + ] + }, + { + "type": "WindowsRestart", + "restartCheckCommand": "write-host \"restarting post Windows updates\"", + "restartTimeout": "10m" + }, + { + "type": "PowerShell", + "name": "Sleep for a min", + "runElevated": true, + "runAsSystem": true, + "inline": [ + "Write-Host \"Sleep for a min\" ", + "Start-Sleep -Seconds 60" + ] + }, + { + "type": "WindowsRestart", + "restartTimeout": "10m" + } + ] + }, + "imageSource": { + "value": { + "type": "PlatformImage", + "publisher": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].publisher]", + "offer": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].offer]", + "sku": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].sku]", + "osAccountType": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osAccountType]", + "version": "latest" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "8764685821617712613" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Image Template to be built by the Azure Image Builder service." + } + }, + "userMsiName": { + "type": "string", + "metadata": { + "description": "Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder." + } + }, + "userMsiResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the user assigned identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "buildTimeoutInMinutes": { + "type": "int", + "defaultValue": 0, + "maxValue": 960, + "minValue": 0, + "metadata": { + "description": "Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes" + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_D2s_v3", + "metadata": { + "description": "Optional. Specifies the size for the VM." + } + }, + "osDiskSizeGB": { + "type": "int", + "defaultValue": 128, + "metadata": { + "description": "Optional. Specifies the size of OS disk." + } + }, + "subnetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of an already existing subnet, e.g. '/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/'. If no value is provided, a new VNET will be created in the target Resource Group." + } + }, + "imageSource": { + "type": "object", + "metadata": { + "description": "Required. Image source definition in object format." + } + }, + "customizationSteps": { + "type": "array", + "metadata": { + "description": "Required. Customization steps to be run when building the VM image." + } + }, + "managedImageName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the managed image that will be created in the AIB resourcegroup." + } + }, + "unManagedImageName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the unmanaged image that will be created in the AIB resourcegroup." + } + }, + "sigImageDefinitionId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/" + } + }, + "imageReplicationRegions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment's location will be taken as a default value." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a unique image template name." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "variables": { + "managedImageName_var": "[format('{0}-{1}', parameters('managedImageName'), parameters('baseTime'))]", + "managedImageId": "[format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/images/{2}', subscription().subscriptionId, resourceGroup().name, variables('managedImageName_var'))]", + "imageReplicationRegions_var": "[if(empty(parameters('imageReplicationRegions')), array(parameters('location')), parameters('imageReplicationRegions'))]", + "managedImage": { + "type": "ManagedImage", + "imageId": "[variables('managedImageId')]", + "location": "[parameters('location')]", + "runOutputName": "[format('{0}-ManagedImage', variables('managedImageName_var'))]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + } + }, + "conditionalManagedImage": "[if(empty(parameters('managedImageName')), createArray(), array(variables('managedImage')))]", + "sharedImage": { + "type": "SharedImage", + "galleryImageId": "[parameters('sigImageDefinitionId')]", + "runOutputName": "[if(not(empty(parameters('sigImageDefinitionId'))), format('{0}-SharedImage', split(parameters('sigImageDefinitionId'), '/')[10]), 'SharedImage')]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + }, + "replicationRegions": "[variables('imageReplicationRegions_var')]" + }, + "conditionalSharedImage": "[if(empty(parameters('sigImageDefinitionId')), createArray(), array(variables('sharedImage')))]", + "unManagedImage": { + "type": "VHD", + "runOutputName": "[format('{0}-VHD', parameters('unManagedImageName'))]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + } + }, + "conditionalUnManagedImage": "[if(empty(parameters('unManagedImageName')), createArray(), array(variables('unManagedImage')))]", + "distribute": "[concat(variables('conditionalManagedImage'), variables('conditionalSharedImage'), variables('conditionalUnManagedImage'))]", + "vnetConfig": { + "subnetId": "[parameters('subnetId')]" + } + }, + "resources": [ + { + "type": "Microsoft.VirtualMachineImages/imageTemplates", + "apiVersion": "2020-02-14", + "name": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId(parameters('userMsiResourceGroup'), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userMsiName')))]": {} + } + }, + "properties": { + "buildTimeoutInMinutes": "[parameters('buildTimeoutInMinutes')]", + "vmProfile": { + "vmSize": "[parameters('vmSize')]", + "osDiskSizeGB": "[parameters('osDiskSizeGB')]", + "vnetConfig": "[if(not(empty(parameters('subnetId'))), variables('vnetConfig'), null())]" + }, + "source": "[parameters('imageSource')]", + "customize": "[parameters('customizationSteps')]", + "distribute": "[variables('distribute')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", + "name": "[format('{0}-{1}-lock', format('{0}-{1}', parameters('name'), parameters('baseTime')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "imageTemplate_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-ImageTemplate-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "4573057817969044259" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", + "metadata": { + "description": "The resource ID of the image template" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image template was deployed into" + } + }, + "name": { + "type": "string", + "value": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", + "metadata": { + "description": "The name of the image template" + } + }, + "runThisCommand": { + "type": "string", + "value": "[format('Invoke-AzResourceAction -ResourceName {0} -ResourceGroupName {1} -ResourceType Microsoft.VirtualMachineImages/imageTemplates -Action Run -Force', format('{0}-{1}', parameters('name'), parameters('baseTime')), resourceGroup().name)]", + "metadata": { + "description": "The command to run in order to trigger the image build" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))]", + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Build-Image-Template-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('imageTemplateBuildName-{0}', parameters('avdOsImage'))]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT2H" + }, + "containerGroupName": { + "value": "[format('imageTemplateBuildName-{0}-aci', parameters('avdOsImage'))]" + }, + "userAssignedIdentities": { + "value": "[if(parameters('createAibManagedIdentity'), createObject(format('{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time'))), '2020-10-01').outputs.resourceId.value), createObject()), createObject(format('{0}', parameters('existingAibManagedIdentityId')), createObject()))]" + }, + "arguments": { + "value": "[format('-subscriptionId ''{0}'' -resourceGroupName ''{1}'' -imageTemplateName ''{2}''', parameters('avdSharedServicesSubId'), variables('avdSharedResourcesRgName'), if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))).outputs.name.value, null()))]" + }, + "scriptContent": { + "value": "[if(parameters('useSharedImage'), ' param(\n [string] [Parameter(Mandatory=$true)] $resourceGroupName,\n [string] [Parameter(Mandatory=$true)] $imageTemplateName,\n [string] [Parameter(Mandatory=$true)] $subscriptionId\n )\n $ErrorActionPreference = \"Stop\"\n Install-Module -Name Az.ImageBuilder -Force\n # Kick off the Azure Image Build \n Write-Host \"Kick off Image buld for $imageTemplateName\"\n Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $resourceGroupName -ResourceType \"Microsoft.VirtualMachineImages/imageTemplates\" -Action Run -Force \n $DeploymentScriptOutputs = @{}\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\n $status=$getStatus.LastRunStatusRunState\n $statusMessage=$getStatus.LastRunStatusMessage\n $startTime=Get-Date\n $reset=$startTime + (New-TimeSpan -Minutes 40)\n Write-Host \"Script will time out in $reset\"\n do {\n $now=Get-Date\n Write-Host \"Getting the current time: $now\"\n if (($now -eq $reset) -or ($now -gt $reset)) {\n break\n }\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\n $status=$getStatus.LastRunStatusRunState\n Write-Host \"Current status of the image build $imageTemplateName is: $status\"\n Write-Host \"Script will time out in $reset\"\n $DeploymentScriptOutputs=$now\n $DeploymentScriptOutputs=$status\n if ($status -eq \"Failed\") {\n Write-Host \"Build failed for image template: $imageTemplateName. Check the Packer logs\"\n $DeploymentScriptOutputs=\"Build Failed\"\n throw \"Build Failed\"\n }\n if (($status -eq \"Canceled\") -or ($status -eq \"Canceling\") ) {\n Write-Host \"User canceled the build. Delete the Image template definition: $imageTemplateName\"\n throw \"User canceled the build.\"\n }\n if ($status -eq \"Succeeded\") {\n Write-Host \"Success. Image template definition: $imageTemplateName is finished \"\n break\n }\n }\n until (($now -eq $reset) -or ($now -gt $reset))\n Write-Host \"Finished check for image build status at $now\"\n\n\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "6451386248046840370" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT6H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Shared-Services-KeyVault-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', parameters('avdSharedServicesSubId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Shared-Services-KeyVault-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedServicesKvName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "enableRbacAuthorization": { + "value": false + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5345269206390435517" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "maxLength": 24, + "metadata": { + "description": "Optional. Name of the Key Vault. If no name is provided, then unique name will be created." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of access policies object" + } + }, + "secrets": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. All secrets to create" + } + }, + "keys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. All keys to create" + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute" + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment" + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios." + } + }, + "enableSoftDelete": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "defaultValue": 90, + "metadata": { + "description": "Optional. softDelete data retention days. It accepts >=7 and <=90." + } + }, + "enableRbacAuthorization": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC." + } + }, + "createMode": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "vaultSku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault" + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "vNetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. " + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "AuditEvent" + ], + "allowedValues": [ + "AuditEvent" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(if(contains(parameters('networkAcls'), 'virtualNetworkRules'), parameters('networkAcls').virtualNetworkRules, createArray()))]", + "input": { + "id": "[format('{0}/subnets/{1}', parameters('vNetId'), if(contains(parameters('networkAcls'), 'virtualNetworkRules'), parameters('networkAcls').virtualNetworkRules, createArray())[copyIndex('virtualNetworkRules')].subnet)]" + } + }, + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ], + "maxNameLength": 24, + "uniquenameUntrim": "[uniqueString(format('Key Vault{0}', parameters('baseTime')))]", + "uniquename": "[if(greater(length(variables('uniquenameUntrim')), variables('maxNameLength')), substring(variables('uniquenameUntrim'), 0, variables('maxNameLength')), variables('uniquenameUntrim'))]", + "name_var": "[if(empty(parameters('name')), variables('uniquename'), parameters('name'))]", + "networkAcls_var": { + "bypass": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').bypass)]", + "defaultAction": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').defaultAction)]", + "virtualNetworkRules": "[if(empty(parameters('networkAcls')), null(), variables('virtualNetworkRules'))]", + "ipRules": "[if(empty(parameters('networkAcls')), null(), if(equals(length(parameters('networkAcls').ipRules), 0), createArray(), parameters('networkAcls').ipRules))]" + }, + "secretList": "[if(not(empty(parameters('secrets'))), parameters('secrets').secureList, createArray())]" + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2019-09-01", + "name": "[variables('name_var')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "enabledForDeployment": "[parameters('enableVaultForDeployment')]", + "enabledForTemplateDeployment": "[parameters('enableVaultForTemplateDeployment')]", + "enabledForDiskEncryption": "[parameters('enableVaultForDiskEncryption')]", + "enableSoftDelete": "[parameters('enableSoftDelete')]", + "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]", + "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]", + "createMode": "[parameters('createMode')]", + "enablePurgeProtection": "[if(not(parameters('enablePurgeProtection')), null(), parameters('enablePurgeProtection'))]", + "tenantId": "[subscription().tenantId]", + "accessPolicies": "[variables('formattedAccessPolicies')]", + "sku": { + "name": "[parameters('vaultSku')]", + "family": "A" + }, + "networkAcls": "[if(empty(parameters('networkAcls')), null(), variables('networkAcls_var'))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-{1}-lock', variables('name_var'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-diagnosticSettingName', variables('name_var'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "accessPolicies": { + "value": "[variables('formattedAccessPolicies')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "123577927532659831" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "defaultValue": "add", + "metadata": { + "description": "Optional. The access policy deployment" + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2021-06-01-preview", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the access policies assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the access policies assignment" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_secrets", + "count": "[length(variables('secretList'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('secretList')[copyIndex()].name]" + }, + "value": { + "value": "[variables('secretList')[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesEnabled'), variables('secretList')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesExp'), variables('secretList')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesNbf'), variables('secretList')[copyIndex()].attributesNbf, -1)]" + }, + "contentType": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'contentType'), variables('secretList')[copyIndex()].contentType, '')]" + }, + "tags": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'tags'), variables('secretList')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'roleAssignments'), variables('secretList')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "10465492711279403166" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "secureString", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "value": "[parameters('value')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "secret_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "4213493396032917091" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the secret." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the secret." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the secret was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_keys", + "count": "[length(parameters('keys'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('keys')[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesEnabled'), parameters('keys')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesExp'), parameters('keys')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesNbf'), parameters('keys')[copyIndex()].attributesNbf, -1)]" + }, + "curveName": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'curveName'), parameters('keys')[copyIndex()].curveName, 'P-256')]" + }, + "keyOps": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keyOps'), parameters('keys')[copyIndex()].keyOps, createArray())]" + }, + "keySize": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keySize'), parameters('keys')[copyIndex()].keySize, -1)]" + }, + "kty": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'kty'), parameters('keys')[copyIndex()].kty, 'EC')]" + }, + "tags": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'tags'), parameters('keys')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'roleAssignments'), parameters('keys')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "13839607759832155507" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "curveName": { + "type": "string", + "defaultValue": "P-256", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "metadata": { + "description": "Optional. The elliptic curve name." + } + }, + "keyOps": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation" + } + }, + "keySize": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA." + } + }, + "kty": { + "type": "string", + "defaultValue": "EC", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "metadata": { + "description": "Optional. The type of the key." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "curveName": "[parameters('curveName')]", + "keyOps": "[parameters('keyOps')]", + "keySize": "[if(not(equals(parameters('keySize'), -1)), parameters('keySize'), null())]", + "kty": "[parameters('kty')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "key_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "13348767636412846394" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the key." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the key." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "17097545501079021235" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + }, + { + "condition": "[not(empty(variables('privateEndpoint_var').privateDnsZoneResourceIds))]", + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/default', variables('privateEndpoint_var').name)]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds)))]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "11003537755691104530" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]", + "metadata": { + "description": "The resource ID of the key vault." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key vault was created in." + } + }, + "name": { + "type": "string", + "value": "[variables('name_var')]", + "metadata": { + "description": "The name of the key vault." + } + }, + "uri": { + "type": "string", + "value": "[reference(resourceId('Microsoft.KeyVault/vaults', variables('name_var'))).vaultUri]", + "metadata": { + "description": "The URI of the key vault." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Shared-Services-Storage-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', parameters('avdSharedServicesSubId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedSResourcesStorageName')]" + }, + "location": { + "value": "[parameters('avdSharedServicesLocation')]" + }, + "storageAccountSku": { + "value": "[if(parameters('avdUseAvailabilityZones'), 'Standard_ZRS', 'Standard_LRS')]" + }, + "storageAccountKind": { + "value": "StorageV2" + }, + "blobServices": { + "value": { + "containers": [ + { + "name": "[variables('avdSharedSResourcesAibContainerName')]", + "publicAccess": "None" + }, + { + "name": "[variables('avdSharedSResourcesScriptsContainerName')]", + "publicAccess": "None" + } + ] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5079633444794670250" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Storage Account." + }, + "maxLength": 24 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "storageAccountKind": { + "type": "string", + "defaultValue": "StorageV2", + "metadata": { + "description": "Optional. Type of Storage Account to create." + }, + "allowedValues": [ + "Storage", + "StorageV2", + "BlobStorage", + "FileStorage", + "BlockBlobStorage" + ] + }, + "storageAccountSku": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage Account Sku Name." + }, + "allowedValues": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS", + "Premium_ZRS", + "Standard_GZRS", + "Standard_RAGZRS" + ] + }, + "storageAccountAccessTier": { + "type": "string", + "defaultValue": "Hot", + "metadata": { + "description": "Optional. Storage Account Access Tier." + }, + "allowedValues": [ + "Hot", + "Cool" + ] + }, + "azureFilesIdentityBasedAuthentication": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Provides the identity based authentication settings for Azure Files." + } + }, + "vNetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Virtual Network Identifier used to create a service endpoint." + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "managementPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Storage Account ManagementPolicies Rules." + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true." + } + }, + "blobServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Blob service and containers to deploy" + } + }, + "fileServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. File service and shares to deploy" + } + }, + "queueServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Queue service and queues to create." + } + }, + "tableServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Table service and tables to create." + } + }, + "allowBlobPublicAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "TLS1_2", + "metadata": { + "description": "Optional. Set the minimum TLS version on request to storage." + }, + "allowedValues": [ + "TLS1_0", + "TLS1_1", + "TLS1_2" + ] + }, + "enableHierarchicalNamespace": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If true, enables Hierarchical Namespace for the storage account" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "basetime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "supportsHttpsTrafficOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Allows https traffic only to storage service if sets to true." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(range(0, if(empty(parameters('networkAcls')), 0, length(parameters('networkAcls').virtualNetworkRules))))]", + "input": { + "id": "[format('{0}/subnets/{1}', parameters('vNetId'), parameters('networkAcls').virtualNetworkRules[range(0, if(empty(parameters('networkAcls')), 0, length(parameters('networkAcls').virtualNetworkRules)))[copyIndex('virtualNetworkRules')]].subnet)]" + } + } + ], + "networkAcls_var": { + "bypass": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').bypass)]", + "defaultAction": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').defaultAction)]", + "virtualNetworkRules": "[if(empty(parameters('networkAcls')), null(), variables('virtualNetworkRules'))]", + "ipRules": "[if(empty(parameters('networkAcls')), null(), if(equals(length(parameters('networkAcls').ipRules), 0), null(), parameters('networkAcls').ipRules))]" + }, + "azureFilesIdentityBasedAuthentication_var": "[parameters('azureFilesIdentityBasedAuthentication')]", + "maxNameLength": 24, + "uniqueStoragenameUntrim": "[format('{0}', uniqueString(format('Storage Account{0}', parameters('basetime'))))]", + "uniqueStoragename": "[if(greater(length(variables('uniqueStoragenameUntrim')), variables('maxNameLength')), substring(variables('uniqueStoragenameUntrim'), 0, variables('maxNameLength')), variables('uniqueStoragenameUntrim'))]", + "saBaseProperties": { + "encryption": { + "keySource": "Microsoft.Storage", + "services": { + "blob": "[if(or(or(or(equals(parameters('storageAccountKind'), 'BlockBlobStorage'), equals(parameters('storageAccountKind'), 'BlobStorage')), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage')), json('{\"enabled\": true}'), null())]", + "file": "[if(or(or(equals(parameters('storageAccountKind'), 'FileStorage'), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage')), json('{\"enabled\": true}'), null())]" + } + }, + "accessTier": "[if(equals(parameters('storageAccountKind'), 'Storage'), null(), parameters('storageAccountAccessTier'))]", + "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]", + "isHnsEnabled": "[if(not(parameters('enableHierarchicalNamespace')), null(), parameters('enableHierarchicalNamespace'))]", + "minimumTlsVersion": "[parameters('minimumTlsVersion')]", + "networkAcls": "[if(empty(parameters('networkAcls')), null(), variables('networkAcls_var'))]", + "allowBlobPublicAccess": "[parameters('allowBlobPublicAccess')]", + "requireInfrastructureEncryption": "[parameters('requireInfrastructureEncryption')]" + }, + "saOptIdBasedAuthProperties": { + "azureFilesIdentityBasedAuthentication": "[variables('azureFilesIdentityBasedAuthentication_var')]" + }, + "saProperties": "[if(empty(parameters('azureFilesIdentityBasedAuthentication')), variables('saBaseProperties'), union(variables('saBaseProperties'), variables('saOptIdBasedAuthProperties')))]", + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2021-06-01", + "name": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]", + "location": "[parameters('location')]", + "kind": "[parameters('storageAccountKind')]", + "sku": { + "name": "[parameters('storageAccountSku')]" + }, + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "properties": "[variables('saProperties')]" + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "name": "[format('{0}-diagnosticSettings', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "properties": { + "storageAccountId": "[if(empty(parameters('diagnosticStorageAccountId')), null(), parameters('diagnosticStorageAccountId'))]", + "workspaceId": "[if(empty(parameters('diagnosticWorkspaceId')), null(), parameters('diagnosticWorkspaceId'))]", + "eventHubAuthorizationRuleId": "[if(empty(parameters('diagnosticEventHubAuthorizationRuleId')), null(), parameters('diagnosticEventHubAuthorizationRuleId'))]", + "eventHubName": "[if(empty(parameters('diagnosticEventHubName')), null(), parameters('diagnosticEventHubName'))]", + "metrics": "[variables('diagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "name": "[format('{0}-{1}-lock', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "storageAccount_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "15421457444845812896" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('privateEndpoints')))]", + "copy": { + "name": "storageAccount_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-PrivateEndpoints-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "1325988067733588028" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/{1}', variables('privateEndpoint_var').name, 'default')]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(variables('privateEndpoint_var').privateDnsZoneResourceIds)]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('managementPolicyRules')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-ManagementPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "rules": { + "value": "[parameters('managementPolicyRules')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "18062634841854271058" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the storage container to deploy" + } + }, + "rules": { + "type": "array", + "metadata": { + "description": "Required. The Storage Account ManagementPolicies Rules" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "condition": "[not(empty(parameters('rules')))]", + "type": "Microsoft.Storage/storageAccounts/managementPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "policy": { + "rules": "[parameters('rules')]" + } + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The resource ID of the deployed management policy" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed management policy" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed management policy" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('blobServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-BlobServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "containers": { + "value": "[if(contains(parameters('blobServices'), 'containers'), parameters('blobServices').containers, createArray())]" + }, + "automaticSnapshotPolicyEnabled": { + "value": "[if(contains(parameters('blobServices'), 'automaticSnapshotPolicyEnabled'), parameters('blobServices').automaticSnapshotPolicyEnabled, false())]" + }, + "deleteRetentionPolicy": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicy'), parameters('blobServices').deleteRetentionPolicy, true())]" + }, + "deleteRetentionPolicyDays": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicyDays'), parameters('blobServices').deleteRetentionPolicyDays, 7)]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogsRetentionInDays'), parameters('blobServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticStorageAccountId'), parameters('blobServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('blobServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubName'), parameters('blobServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'logsToEnable'), parameters('blobServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'metricsToEnable'), parameters('blobServices').metricsToEnable, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticWorkspaceId'), parameters('blobServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "18210342169419224691" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the blob service" + } + }, + "deleteRetentionPolicy": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service." + } + }, + "deleteRetentionPolicyDays": { + "type": "int", + "defaultValue": 7, + "metadata": { + "description": "Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365." + } + }, + "automaticSnapshotPolicyEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Automatic Snapshot is enabled if set to true." + } + }, + "containers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Blob containers to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "deleteRetentionPolicy": { + "enabled": "[parameters('deleteRetentionPolicy')]", + "days": "[parameters('deleteRetentionPolicyDays')]" + }, + "automaticSnapshotPolicyEnabled": "[parameters('automaticSnapshotPolicyEnabled')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "blobServices_container", + "count": "[length(parameters('containers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Container-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('containers')[copyIndex()].name]" + }, + "publicAccess": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'publicAccess'), parameters('containers')[copyIndex()].publicAccess, 'None')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'roleAssignments'), parameters('containers')[copyIndex()].roleAssignments, createArray())]" + }, + "immutabilityPolicyProperties": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'immutabilityPolicyProperties'), parameters('containers')[copyIndex()].immutabilityPolicyProperties, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "6352948993625128419" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage container to deploy" + } + }, + "immutabilityPolicyName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "publicAccess": { + "type": "string", + "defaultValue": "None", + "metadata": { + "description": "Optional. Specifies whether data in the container may be accessed publicly and the level of access." + }, + "allowedValues": [ + "Container", + "Blob", + "None" + ] + }, + "immutabilityPolicyProperties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Configure immutability policy." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "properties": { + "publicAccess": "[parameters('publicAccess')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('immutabilityPolicyProperties')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[parameters('immutabilityPolicyName')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('blobServicesName')]" + }, + "containerName": { + "value": "[parameters('name')]" + }, + "immutabilityPeriodSinceCreationInDays": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'immutabilityPeriodSinceCreationInDays'), parameters('immutabilityPolicyProperties').immutabilityPeriodSinceCreationInDays, 365)]" + }, + "allowProtectedAppendWrites": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'allowProtectedAppendWrites'), parameters('immutabilityPolicyProperties').allowProtectedAppendWrites, true())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "2146595313239270910" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "containerName": { + "type": "string", + "metadata": { + "description": "Required. Name of the container to apply the policy to" + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "immutabilityPeriodSinceCreationInDays": { + "type": "int", + "defaultValue": 365, + "metadata": { + "description": "Optional. The immutability period for the blobs in the container since the policy creation, in days." + } + }, + "allowProtectedAppendWrites": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "properties": { + "immutabilityPeriodSinceCreationInDays": "[parameters('immutabilityPeriodSinceCreationInDays')]", + "allowProtectedAppendWrites": "[parameters('allowProtectedAppendWrites')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed immutability policy." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed immutability policy." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed immutability policy." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "container_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7411080002413355866" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}/containers/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed container" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed container" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed container" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed blob service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed blob service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the deployed blob service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('fileServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-FileServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogsRetentionInDays'), parameters('fileServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticStorageAccountId'), parameters('fileServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('fileServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubName'), parameters('fileServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'logsToEnable'), parameters('fileServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'metricsToEnable'), parameters('fileServices').metricsToEnable, createArray())]" + }, + "protocolSettings": { + "value": "[if(contains(parameters('fileServices'), 'protocolSettings'), parameters('fileServices').protocolSettings, createObject())]" + }, + "shareDeleteRetentionPolicy": { + "value": "[if(contains(parameters('fileServices'), 'shareDeleteRetentionPolicy'), parameters('fileServices').shareDeleteRetentionPolicy, createObject('enabled', true(), 'days', 7))]" + }, + "shares": { + "value": "[if(contains(parameters('fileServices'), 'shares'), parameters('fileServices').shares, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticWorkspaceId'), parameters('fileServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "17547592645947527945" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "protocolSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Protocol settings for file service" + } + }, + "shareDeleteRetentionPolicy": { + "type": "object", + "defaultValue": { + "enabled": true, + "days": 7 + }, + "metadata": { + "description": "Optional. The service properties for soft delete." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "shares": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. File shares to create." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "protocolSettings": "[parameters('protocolSettings')]", + "shareDeleteRetentionPolicy": "[parameters('shareDeleteRetentionPolicy')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "fileServices_shares", + "count": "[length(parameters('shares'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-File-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "fileServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('shares')[copyIndex()].name]" + }, + "sharedQuota": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'sharedQuota'), parameters('shares')[copyIndex()].sharedQuota, 5120)]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'roleAssignments'), parameters('shares')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "835165494525466514" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "fileServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the file share to create" + } + }, + "sharedQuota": { + "type": "int", + "defaultValue": 5120, + "metadata": { + "description": "Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/fileServices/shares", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "properties": { + "shareQuota": "[parameters('sharedQuota')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "fileShare_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "12086118320906724195" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}/shares/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('queueServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-QueueServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogsRetentionInDays'), parameters('queueServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticStorageAccountId'), parameters('queueServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('queueServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubName'), parameters('queueServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'logsToEnable'), parameters('queueServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'metricsToEnable'), parameters('queueServices').metricsToEnable, createArray())]" + }, + "queues": { + "value": "[if(contains(parameters('queueServices'), 'queues'), parameters('queueServices').queues, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticWorkspaceId'), parameters('queueServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "10257941952160586343" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "queues": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Queues to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/queueServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "queueServices_queues", + "count": "[length(parameters('queues'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Queue-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "queueServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('queues')[copyIndex()].name]" + }, + "metadata": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'metadata'), parameters('queues')[copyIndex()].metadata, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'roleAssignments'), parameters('queues')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "293456068355238307" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "queueServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage queue to deploy" + } + }, + "metadata": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Required. A name-value pair that represents queue metadata." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/queueServices/queues", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "queue_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[format('{0}', resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "5956644999738826568" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Dsms Role (deprecated)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b')]", + "Dsms Role (do not use)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f')]", + "GenevaWarmPathResourceContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}/queues/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed queue" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed queue" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed queue" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('tableServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-TableServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogsRetentionInDays'), parameters('tableServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticStorageAccountId'), parameters('tableServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('tableServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubName'), parameters('tableServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'logsToEnable'), parameters('tableServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'metricsToEnable'), parameters('tableServices').metricsToEnable, createArray())]" + }, + "tables": { + "value": "[if(contains(parameters('tableServices'), 'tables'), parameters('tableServices').tables, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticWorkspaceId'), parameters('tableServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "1694742398547498732" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. tables to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/tableServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/tableServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "tableServices_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Table-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "tableServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "1515794753228730493" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "tableServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/tableServices/tables", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]" + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.6.1.6515", + "templateHash": "7622300702201449576" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices/tables', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed table service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed table service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed table service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "metadata": { + "description": "The resource ID of the deployed storage account" + } + }, + "name": { + "type": "string", + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]", + "metadata": { + "description": "The name of the deployed storage account" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed storage account" + } + }, + "primaryBlobEndpoint": { + "type": "string", + "value": "[if(and(not(empty(parameters('blobServices'))), contains(parameters('blobServices'), 'containers')), reference(format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2019-04-01').primaryEndpoints.blob, '')]", + "metadata": { + "description": "The primary blob endpoint reference if blob services are deployed." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2021-06-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2021-06-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('avdSharedServicesSubId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + } + ] +} \ No newline at end of file diff --git a/workload/arm/deploy.json b/workload/arm/deploy.json new file mode 100644 index 000000000..a7baabe9d --- /dev/null +++ b/workload/arm/deploy.json @@ -0,0 +1,24134 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11087167760621999096" + } + }, + "parameters": { + "deploymentPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. The name of the resource group to deploy" + }, + "maxLength": 4, + "minLength": 2 + }, + "avdSubOrgsOption": { + "type": "string", + "defaultValue": "Multiple", + "metadata": { + "description": "Required. AVD subscription model (Default: Multiple)" + }, + "allowedValues": [ + "Multiple", + "Single" + ] + }, + "avdSessionHostLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. Location where to deploy compute services" + } + }, + "avdManagementPlaneLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. Location where to deploy AVD management plane" + } + }, + "avdSingleSubsId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. AVD shared services subscription ID, single subscriptions scenario" + } + }, + "avdShrdlSubsId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. AVD shared services subscription ID, multiple subscriptions scenario" + } + }, + "avdWrklSubsId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. AVD workload subscription ID, multiple subscriptions scenario" + } + }, + "avdEnterpriseAppObjectId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Azure Virtual Desktop Enterprise Application object ID. " + } + }, + "avdVmLocalUserName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. AVD session host local credentials" + } + }, + "avdVmLocalUserPassword": { + "type": "secureString", + "defaultValue": "" + }, + "avdIdentityDomainName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. AD domain name" + } + }, + "avdDomainJoinUserName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. AVD session host domain join credentials" + } + }, + "avdDomainJoinUserPassword": { + "type": "secureString", + "defaultValue": "" + }, + "avdOuPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. OU path to join AVd VMs" + } + }, + "avdHostPoolType": { + "type": "string", + "defaultValue": "Pooled", + "metadata": { + "description": "Optional. AVD host pool type (Default: Pooled)" + }, + "allowedValues": [ + "Personal", + "Pooled" + ] + }, + "avdPersonalAssignType": { + "type": "string", + "defaultValue": "Automatic", + "metadata": { + "description": "Optional. AVD host pool type (Default: Automatic)" + }, + "allowedValues": [ + "Automatic", + "Direct" + ] + }, + "avdHostPoolloadBalancerType": { + "type": "string", + "defaultValue": "BreadthFirst", + "metadata": { + "description": "Required. AVD host pool load balacing type (Default: BreadthFirst)" + }, + "allowedValues": [ + "BreadthFirst", + "DepthFirst" + ] + }, + "avhHostPoolMaxSessions": { + "type": "int", + "defaultValue": 15, + "metadata": { + "description": "Optional. AVD host pool maximum number of user sessions per session host" + } + }, + "avdStartVMOnConnect": { + "type": "bool", + "metadata": { + "description": "Optional. AVD host pool start VM on Connect" + } + }, + "createStartVmOnConnectCustomRole": { + "type": "bool", + "metadata": { + "description": "Create custom Start VM on connect role" + } + }, + "avdDeployRAppGroup": { + "type": "bool", + "metadata": { + "description": "Optional. AVD deploy remote app application group" + } + }, + "avdHostPoolRdpProperty": { + "type": "string", + "defaultValue": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2", + "metadata": { + "description": "Optional. AVD host pool Custom RDP properties" + } + }, + "createAvdVnet": { + "type": "bool", + "metadata": { + "description": "Create new virtual network" + } + }, + "existingVnetSubnetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Existing virtual network subnet" + } + }, + "existingHubVnetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Existing hub virtual network for perring" + } + }, + "avdVnetworkAddressPrefixes": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "AVD virtual network address prefixes" + } + }, + "avdVnetworkSubnetAddressPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "AVD virtual network subnet address prefix" + } + }, + "customDnsIps": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "custom DNS servers IPs" + } + }, + "vNetworkGatewayOnHub": { + "type": "bool", + "metadata": { + "description": "Does the hub contains a virtual network gateway" + } + }, + "avdFslogixFileShareQuotaSize": { + "type": "int", + "defaultValue": 512, + "metadata": { + "description": "Optional. Fslogix file share size (Default: 5TB)" + } + }, + "avdDeploySessionHosts": { + "type": "bool", + "metadata": { + "description": "Deploy new session hosts" + } + }, + "avdDeploySessionHostsCount": { + "type": "int", + "metadata": { + "description": "Cuantity of session hosts to deploy" + }, + "maxValue": 500, + "minValue": 1 + }, + "avdUseAvailabilityZones": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)" + } + }, + "fsLogixstorageSku": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Storage account SKU for FSLogix storage. Recommended tier is Premium LRS or Premium ZRS (where available)" + } + }, + "encryptionAtHost": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "avdSessionHostsSize": { + "type": "string", + "defaultValue": "Standard_D2s_v4", + "metadata": { + "description": "Session host VM size (Defualt: Standard_D2s_v4) " + } + }, + "avdSessionHostDiskType": { + "type": "string", + "defaultValue": "Standard_LRS", + "metadata": { + "description": "OS disk type for session host (Defualt: Standard_LRS) " + } + }, + "aiblocation": { + "type": "string", + "defaultValue": "eastus2", + "metadata": { + "description": "Azure image builder location (Defualt: eastus2)" + }, + "allowedValues": [ + "eastus", + "eastus2", + "westcentralus", + "westus", + "westus2", + "westus3", + "southcentralus", + "northeurope", + "westeurope", + "southeastasia", + "australiasoutheast", + "australiaeast", + "uksouth", + "ukwest" + ] + }, + "createAibCustomRole": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Create custom azure image builder role" + } + }, + "avdOsImage": { + "type": "string", + "defaultValue": "win10_21h2", + "metadata": { + "description": "Required. AVD OS image source (Default: win10-21h2)" + }, + "allowedValues": [ + "win10_21h2_office", + "win10_21h2", + "win11_21h2_office", + "win11_21h2" + ] + }, + "useSharedImage": { + "type": "bool", + "metadata": { + "description": "Set to deploy image from Azure Compute Gallery" + } + }, + "avdImageRegionsReplicas": { + "type": "array", + "defaultValue": [ + "eastus2" + ], + "metadata": { + "description": "Regions to replicate AVD images (Defualt: eastus2)" + } + }, + "createAibManagedIdentity": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Create azure image Builder managed identity" + } + }, + "time": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "Do not modify, used to set unique value for resource deployment" + } + } + }, + "variables": { + "deploymentPrefixLowercase": "[toLower(parameters('deploymentPrefix'))]", + "avdSessionHostLocationLowercase": "[toLower(parameters('avdSessionHostLocation'))]", + "avdManagementPlaneLocationLowercase": "[toLower(parameters('avdManagementPlaneLocation'))]", + "avdWrklSubscriptionId": "[if(equals(parameters('avdSubOrgsOption'), 'Multiple'), parameters('avdWrklSubsId'), parameters('avdSingleSubsId'))]", + "avdShrdlSubscriptionId": "[if(equals(parameters('avdSubOrgsOption'), 'Multiple'), parameters('avdShrdlSubsId'), parameters('avdSingleSubsId'))]", + "avdServiceObjectsRgName": "[format('rg-{0}-avd-{1}-service-objects', variables('avdManagementPlaneLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdNetworkObjectsRgName": "[format('rg-{0}-avd-{1}-network', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdComputeObjectsRgName": "[format('rg-{0}-avd-{1}-pool-compute', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdStorageObjectsRgName": "[format('rg-{0}-avd-{1}-storage', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdSharedResourcesRgName": "[format('rg-{0}-avd-shared-resources', variables('avdSessionHostLocationLowercase'))]", + "imageGalleryName": "[format('avdgallery{0}', variables('avdSessionHostLocationLowercase'))]", + "avdVnetworkName": "[format('vnet-{0}-avd-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdVnetworkSubnetName": "[format('avd-{0}', variables('deploymentPrefixLowercase'))]", + "avdNetworksecurityGroupName": "[format('nsg-{0}-avd-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdRouteTableName": "[format('udr-{0}-avd-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdApplicationsecurityGroupName": "[format('asg-{0}-avd-{1}', variables('avdSessionHostLocationLowercase'), variables('deploymentPrefixLowercase'))]", + "avdVNetworkPeeringName": "[format('{0}-peering-avd-{1}', uniqueString(variables('deploymentPrefixLowercase'), parameters('avdSessionHostLocation')), variables('deploymentPrefixLowercase'))]", + "avdWorkSpaceName": "[format('avdws-{0}', variables('deploymentPrefixLowercase'))]", + "avdHostPoolName": "[format('avdhp-{0}', variables('deploymentPrefixLowercase'))]", + "avdApplicationGroupNameDesktop": "[format('avd-dag-{0}', variables('deploymentPrefixLowercase'))]", + "avdApplicationGroupNameRApp": "[format('avd-raag-{0}', variables('deploymentPrefixLowercase'))]", + "aibManagedIdentityName": "avd-uai-aib", + "deployScriptManagedIdentityName": "avd-uai-deployScript", + "imageDefinitionsTemSpecName": "[format('AVDImageDefinition_{0}', parameters('avdOsImage'))]", + "imageVmSize": "Standard_D4s_v3", + "avdOsImageDefinitions": { + "win10_21h2_office": { + "name": "Windows10_21H2_Office", + "osType": "Windows", + "osState": "Generalized", + "offer": "office-365", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win10-21h2-avd-m365", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V1" + }, + "win10_21h2": { + "name": "Windows10_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "windows-10", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win10-21h2-avd", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V1" + }, + "win11_21h2_office": { + "name": "Windows11_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "office-365", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win11-21h2-avd-m365", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V2" + }, + "win11_21h2": { + "name": "Windows11_21H2", + "osType": "Windows", + "osState": "Generalized", + "offer": "windows-11", + "publisher": "MicrosoftWindowsDesktop", + "sku": "win11-21h2-avd", + "osAccountType": "Standard_LRS", + "hyperVGeneration": "V2" + } + }, + "marketPlaceGalleryWindows": { + "win10_21h2_office": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "office-365", + "sku": "win10-21h2-avd-m365", + "version": "latest" + }, + "win10_21h2": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "windows-10", + "sku": "win10-21h2-avd", + "version": "latest" + }, + "win11_21h2_office": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "office-365", + "sku": "win11-21h2-avd-m365", + "version": "latest" + }, + "win11_21h2": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-11", + "sku": "win11-21h2-avd", + "version": "latest" + } + }, + "baseScriptUri": "https://raw.githubusercontent.com/nataliakon/ResourceModules/AVD-Accelerator/workload/", + "fslogixScriptUri": "[format('{0}Scripts/Set-FSLogixRegKeys.ps1', variables('baseScriptUri'))]", + "fsLogixScript": "./Set-FSLogixRegKeys.ps1", + "fslogixSharePath": "[format('\\\\{0}.file.{1}\\{2}', variables('avdFslogixStorageName'), environment().suffixes.storage, variables('avdFslogixFileShareName'))]", + "FsLogixScriptArguments": "[format('-volumeshare {0}', variables('fslogixSharePath'))]", + "avdAgentPackageLocation": "[format('https://wvdportalstorageblob.blob.{0}/galleryartifacts/Configuration_10-6-2021.zip', environment().suffixes.storage)]", + "avdFslogixStorageName": "[format('fslogix{0}{1}', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSessionHostLocationLowercase')), variables('deploymentPrefixLowercase'))]", + "avdFslogixFileShareName": "[format('fslogix-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedSResourcesStorageName": "[format('avd{0}shared', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSessionHostLocationLowercase')))]", + "avdSharedSResourcesAibContainerName": "[format('aib-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedSResourcesScriptsContainerName": "[format('scripts-{0}', variables('deploymentPrefixLowercase'))]", + "avdSharedServicesKvName": "[format('avd-{0}-shared', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSessionHostLocationLowercase')))]", + "avdWrklKvName": "[format('avd-{0}-{1}', uniqueString(variables('deploymentPrefixLowercase'), variables('avdSessionHostLocationLowercase')), variables('deploymentPrefixLowercase'))]", + "avdSessionHostNamePrefix": "[format('avdsh-{0}', parameters('deploymentPrefix'))]", + "avdAvailabilitySetName": "[format('avdas-{0}', parameters('deploymentPrefix'))]", + "allAvailabilityZones": "[pickZones('Microsoft.Compute', 'virtualMachines', parameters('avdSessionHostLocation'), 3)]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Shared-Resources-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdShrdlSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedResourcesRgName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2929043714372245867" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15729189627955918611" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3400142064018598968" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-ServiceObjects-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdWrklSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdServiceObjectsRgName')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2929043714372245867" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15729189627955918611" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3400142064018598968" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Network-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdWrklSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdNetworkObjectsRgName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2929043714372245867" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15729189627955918611" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3400142064018598968" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Compute-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdWrklSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdComputeObjectsRgName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2929043714372245867" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15729189627955918611" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3400142064018598968" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-RG-Storage-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdWrklSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdStorageObjectsRgName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2929043714372245867" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group" + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the storage account resource." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2019-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-{1}-Lock', uniqueString(deployment().name, parameters('location')), parameters('lock'))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]" + }, + "level": { + "value": "[parameters('lock')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15729189627955918611" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Lock" + } + }, + "level": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Set lock level." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + } + }, + "variables": { + "lockNotes": { + "CanNotDelete": "Cannot delete resource or child resources.", + "ReadOnly": "Cannot modify the resource or child resources." + }, + "lockName": "[if(empty(parameters('name')), format('{0}-lock', parameters('level')), parameters('name'))]" + }, + "resources": [ + { + "condition": "[not(equals(parameters('level'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "name": "[variables('lockName')]", + "properties": { + "level": "[parameters('level')]", + "notes": "[variables('lockNotes')[parameters('level')]]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Authorization/locks', variables('lockName'))]", + "metadata": { + "description": "The resource ID of the lock" + } + }, + "name": { + "type": "string", + "value": "[variables('lockName')]", + "metadata": { + "description": "The name of the lock" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "resourceGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceGroupName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3400142064018598968" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceGroupName": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "AcrDelete": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')]", + "AcrImageSigner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')]", + "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]", + "AcrPush": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')]", + "AcrQuarantineReader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')]", + "AcrQuarantineWriter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')]", + "API Management Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')]", + "API Management Service Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e022efe7-f5ba-4159-bbe4-b44f577e9b61')]", + "API Management Service Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Application Insights Component Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ae349356-3a1b-4a5e-921d-050484c6347e')]", + "Application Insights Snapshot Debugger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '08954f03-6346-4c2e-81c0-ec3a5cfae23b')]", + "Attestation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e')]", + "Attestation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Azure Connected Machine Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7')]", + "Azure Connected Machine Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cd570a14-e51a-42ad-bac8-bafd67325302')]", + "Azure Digital Twins Owner (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'bcd981a7-7f74-457b-83e1-cceb9e632ffe')]", + "Azure Digital Twins Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd57506d4-4c8d-48b1-8587-93c323f6a5a3')]", + "Azure Event Hubs Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f526a384-b230-433a-b45c-95f59c4a2dec')]", + "Azure Event Hubs Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde')]", + "Azure Event Hubs Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2b629674-e913-4c01-ae53-ef4638d8f975')]", + "Azure Kubernetes Service Cluster Admin Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8')]", + "Azure Kubernetes Service Cluster User Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4abbcc35-e782-43d8-92c5-2d3f1bd2253f')]", + "Azure Kubernetes Service Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8')]", + "Azure Maps Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204')]", + "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", + "Azure Sentinel Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ab8e14d6-4a74-4a29-9ba8-549422addade')]", + "Azure Sentinel Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d289c81-5878-46d4-8554-54e1e3d8b5cb')]", + "Azure Sentinel Responder": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e150937-b8fe-4cfb-8069-0eaf05ecd056')]", + "Azure Service Bus Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')]", + "Azure Service Bus Data Receiver": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0')]", + "Azure Service Bus Data Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39')]", + "Azure Stack Registration Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6f12a6df-dd06-4f3e-bcb1-ce8be600526a')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Billing Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64')]", + "BizTalk Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e3c6656-6cfa-4708-81fe-0de47ac73342')]", + "Blockchain Member Node Access (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '31a002a1-acaf-453e-8a5b-297c9ca1ea24')]", + "Blueprint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '41077137-e803-4205-871c-5a86e6a753b4')]", + "Blueprint Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '437d2ced-4a38-4302-8479-ed2bcb43d090')]", + "CDN Endpoint Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '426e0c7f-0c7e-4658-b36f-ff54d6c29b45')]", + "CDN Endpoint Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '871e35f6-b5c1-49cc-a043-bde969a0f2cd')]", + "CDN Profile Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ec156ff8-a8d1-4d15-830c-5b80698ca432')]", + "CDN Profile Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8f96442b-4075-438f-813d-ad51ab4019af')]", + "Classic Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f')]", + "Classic Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86e8f5dc-a6e9-4c67-9d15-de283e8eac25')]", + "Classic Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '985d6b00-f706-48f5-a6fe-d0ca12fb668d')]", + "Classic Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]", + "ClearDB MySQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9106cda0-8a86-4e81-b686-29a22c54effe')]", + "Cognitive Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "Cognitive Services Custom Vision Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3')]", + "Cognitive Services Custom Vision Deployment": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5c4089e1-6d96-4d2f-b296-c1bc7137275f')]", + "Cognitive Services Custom Vision Labeler": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '88424f51-ebe7-446f-bc41-7fa16989e96c')]", + "Cognitive Services Custom Vision Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '93586559-c37d-4a6b-ba08-b9f0940c2d73')]", + "Cognitive Services Custom Vision Trainer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b')]", + "Cognitive Services Data Reader (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b59867f0-fa02-499b-be73-45a86b5b3e1c')]", + "Cognitive Services QnA Maker Editor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f4cc2bf9-21be-47a1-bdf1-5c5804381025')]", + "Cognitive Services QnA Maker Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '466ccd10-b268-4a11-b098-b4849f024126')]", + "Cognitive Services User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "Cost Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '434105ed-43f6-45c7-a02f-909b2ba83430')]", + "Cost Management Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '72fafb9e-0641-4937-9268-a91bfd8191a3')]", + "Data Box Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'add466c9-e687-43fc-8d98-dfcf8d720be5')]", + "Data Box Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027')]", + "Data Factory Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '673868aa-7521-48a0-acc6-0f60742d39f5')]", + "Data Lake Analytics Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '47b7735b-770e-4598-a7da-8b91488b4c88')]", + "Data Purger": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '150f5e0c-0603-4f03-8c7f-cf70034c4e90')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "EventGrid EventSubscription Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '428e0ff0-5e57-4d9c-a221-2c70d0e0a443')]", + "EventGrid EventSubscription Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2414bbcf-6497-4faf-8c65-045460748405')]", + "Experimentation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a33b-edd6ce5c915c')]", + "Experimentation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f646f1b-fa08-80eb-a22b-edd6ce5c915c')]", + "Experimentation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1')]", + "FHIR Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5a1fc7df-4bf1-4951-a576-89034ee01acd')]", + "FHIR Data Exporter": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3db33094-8700-4567-8da5-1501d4e7e843')]", + "FHIR Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4c8d0bbc-75d3-4935-991f-5f3c56d81508')]", + "FHIR Data Writer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3f88fce4-5892-4214-ae73-ba5294559913')]", + "Graph Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b60367af-1334-4454-b71e-769d9a4f83d9')]", + "HDInsight Cluster Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '61ed4efc-fab3-44fd-b111-e24485cc132a')]", + "HDInsight Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8d8d5a11-05d3-4bda-a417-a08778121c7c')]", + "Hierarchy Settings Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '350f8d15-c687-4448-8ae1-157740a3936d')]", + "Hybrid Server Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb')]", + "Hybrid Server Resource Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '48b40c6e-82e0-4eb3-90d5-19e40f49b624')]", + "Integration Service Environment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8')]", + "Integration Service Environment Developer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec')]", + "Intelligent Systems Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '03a6d094-3444-4b3d-88af-7477090a9e5e')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Knowledge Consumer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ee361c5d-f7b5-4119-b4b6-892157c8f64c')]", + "Kubernetes Cluster - Azure Arc Onboarding": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '34e09817-6cbe-4d01-b1a2-e0eac5743d41')]", + "Lab Creator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Logic App Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Managed Services Registration assignment Delete ": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '91c1777a-f3dc-4fae-b103-61d183457e46')]", + "Management Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c')]", + "Management Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ac63b705-f282-497d-ac71-919bf39d939d')]", + "Marketplace Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dd920d6d-f481-47f1-b461-f338c46b2d9f')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "New Relic APM Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d28c62d-5b37-4476-8438-e587778df237')]", + "Object Understanding Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4dd61c23-6743-42fe-a388-d8bdd41cb745')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Policy Insights Data Writer (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '66bb4e9e-b016-4a94-8249-4c0511c2be84')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "Remote Rendering Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3df8b902-2a6f-47c7-8cc5-360e9b272a7e')]", + "Remote Rendering Client": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd39065c4-c120-43c9-ab0a-63eed9795f0a')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Scheduler Job Collections Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '188a0f2f-5c9e-469b-ae67-2aa5ce574b94')]", + "Search Service Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Assessment Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '612c2aa1-cb24-443b-ac28-3ab7272de6f5')]", + "Security Manager (Legacy)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "SignalR AccessKey Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '04165923-9d83-45d5-8227-78b77b0a687e')]", + "SignalR Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Site Recovery Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'dbaa88c4-0c30-4179-9fb3-46319faa6149')]", + "Spatial Anchors Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827')]", + "Spatial Anchors Account Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '70bbe301-9835-447d-afdd-19eb3167307c')]", + "Spatial Anchors Account Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5d51204f-eb77-4b1c-b86a-2ec626c49413')]", + "SQL DB Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "SQL Server Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Support Request Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Traffic Manager Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]", + "Workbook Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e8ddcd69-c73f-4f9f-9844-4100522f16ad')]", + "Workbook Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b279062a-9be3-42a0-92ae-8b3cf002ec4d')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('resourceGroupName'), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the resource group" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the resource group" + } + } + } + } + } + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-NSG-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdNetworkObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdNetworksecurityGroupName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "8958490719537755147" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Network Security Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "networkSecurityGroupSecurityRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the NSG resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "NetworkSecurityGroupEvent", + "NetworkSecurityGroupRuleCounter" + ], + "allowedValues": [ + "NetworkSecurityGroupEvent", + "NetworkSecurityGroupRuleCounter" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "securityRules", + "count": "[length(parameters('networkSecurityGroupSecurityRules'))]", + "input": { + "name": "[parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].name]", + "properties": { + "description": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'description'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.description, '')]", + "protocol": "[parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.protocol]", + "sourcePortRange": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'sourcePortRange'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.sourcePortRange, '')]", + "destinationPortRange": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'destinationPortRange'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.destinationPortRange, '')]", + "sourceAddressPrefix": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'sourceAddressPrefix'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.sourceAddressPrefix, '')]", + "destinationAddressPrefix": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'destinationAddressPrefix'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.destinationAddressPrefix, '')]", + "access": "[parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.access]", + "priority": "[int(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.priority)]", + "direction": "[parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.direction]", + "sourcePortRanges": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'sourcePortRanges'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.sourcePortRanges, null())]", + "destinationPortRanges": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'destinationPortRanges'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.destinationPortRanges, null())]", + "sourceAddressPrefixes": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'sourceAddressPrefixes'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.sourceAddressPrefixes, null())]", + "destinationAddressPrefixes": "[if(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'destinationAddressPrefixes'), parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.destinationAddressPrefixes, null())]", + "sourceApplicationSecurityGroups": "[if(and(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'sourceApplicationSecurityGroupIds'), not(empty(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.sourceApplicationSecurityGroupIds))), concat(createArray(), array(json(format('{{\"id\": \"{0}\", \"location\": \"{1}\"}}', parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.sourceApplicationSecurityGroupIds[0], parameters('location'))))), null())]", + "destinationApplicationSecurityGroups": "[if(and(contains(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties, 'destinationApplicationSecurityGroupIds'), not(empty(parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.destinationApplicationSecurityGroupIds))), concat(createArray(), array(json(format('{{\"id\": \"{0}\", \"location\": \"{1}\"}}', parameters('networkSecurityGroupSecurityRules')[copyIndex('securityRules')].properties.destinationApplicationSecurityGroupIds[0], parameters('location'))))), null())]" + } + } + } + ] + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "networkSecurityGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-NSG-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "16573338072012824158" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the network security group was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the network security group" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the network security group" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Network-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-ASG-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdApplicationsecurityGroupName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "18177366016846151882" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application Security Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/applicationSecurityGroups", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": {} + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/applicationSecurityGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "applicationSecurityGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppSecurityGroup-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "1947899051634330033" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "ExpressRoute Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7896-14b4-4889-afef-fbb65a96e5a2')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/applicationSecurityGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the application security group was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/applicationSecurityGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the application security group" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the application security group" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Compute-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-UDR-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdNetworkObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdRouteTableName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "786036265375512660" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name given for the hub route table." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "routes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An Array of Routes to be established within the hub route table." + } + }, + "disableBgpRoutePropagation": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Switch to disable BGP route propagation." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/routeTables", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "routes": "[parameters('routes')]", + "disableBgpRoutePropagation": "[parameters('disableBgpRoutePropagation')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/routeTables/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/routeTables', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "routeTable_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-RouteTable-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/routeTables', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "1754991853083842331" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/routeTables/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/routeTables', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the route table was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the route table" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/routeTables', parameters('name'))]", + "metadata": { + "description": "The resource ID of the route table" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Network-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createAvdVnet')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-vNet-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdNetworkObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdVnetworkName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "addressPrefixes": { + "value": "[array(parameters('avdVnetworkAddressPrefixes'))]" + }, + "dnsServers": { + "value": "[if(not(empty(parameters('customDnsIps'))), array(parameters('customDnsIps')), createArray())]" + }, + "virtualNetworkPeerings": { + "value": [ + { + "remoteVirtualNetworkId": "[parameters('existingHubVnetResourceId')]", + "name": "[variables('avdVNetworkPeeringName')]", + "allowForwardedTraffic": true, + "allowGatewayTransit": false, + "allowVirtualNetworkAccess": true, + "doNotVerifyRemoteGateways": true, + "useRemoteGateways": "[if(parameters('vNetworkGatewayOnHub'), true(), false())]", + "remotePeeringEnabled": true, + "remotePeeringName": "[variables('avdVNetworkPeeringName')]", + "remotePeeringAllowForwardedTraffic": true, + "remotePeeringAllowGatewayTransit": "[if(parameters('vNetworkGatewayOnHub'), true(), false())]", + "remotePeeringAllowVirtualNetworkAccess": true, + "remotePeeringDoNotVerifyRemoteGateways": true, + "remotePeeringUseRemoteGateways": false + } + ] + }, + "subnets": { + "value": [ + { + "name": "[variables('avdVnetworkSubnetName')]", + "addressPrefix": "[parameters('avdVnetworkSubnetAddressPrefix')]", + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled", + "networkSecurityGroupName": "[variables('avdNetworksecurityGroupName')]", + "routeTableName": "[variables('avdRouteTableName')]" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "6382577947927484535" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The Virtual Network (vNet) Name." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "addressPrefixes": { + "type": "array", + "metadata": { + "description": "Required. An Array of 1 or more IP Address Prefixes for the Virtual Network." + } + }, + "subnets": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An Array of subnets to deploy to the Virtual Network." + } + }, + "dnsServers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. DNS Servers associated to the Virtual Network." + } + }, + "ddosProtectionPlanId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the DDoS protection plan to assign the VNET to. If it's left blank, DDoS protection will not be configured. If it's provided, the VNET created by this template will be attached to the referenced DDoS protection plan. The DDoS protection plan can exist in the same or in a different subscription." + } + }, + "virtualNetworkPeerings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Virtual Network Peerings configurations" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "VMProtectionAlerts" + ], + "allowedValues": [ + "VMProtectionAlerts" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "dnsServers_var": { + "dnsServers": "[array(parameters('dnsServers'))]" + }, + "ddosProtectionPlan": { + "id": "[parameters('ddosProtectionPlanId')]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "subnets", + "count": "[length(parameters('subnets'))]", + "input": { + "name": "[parameters('subnets')[copyIndex('subnets')].name]", + "properties": { + "addressPrefix": "[parameters('subnets')[copyIndex('subnets')].addressPrefix]", + "delegations": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'delegations'), parameters('subnets')[copyIndex('subnets')].delegations, null())]", + "privateEndpointNetworkPolicies": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'privateEndpointNetworkPolicies'), parameters('subnets')[copyIndex('subnets')].privateEndpointNetworkPolicies, null())]", + "privateLinkServiceNetworkPolicies": "[if(contains(parameters('subnets')[copyIndex('subnets')], 'privateLinkServiceNetworkPolicies'), parameters('subnets')[copyIndex('subnets')].privateLinkServiceNetworkPolicies, null())]" + } + } + } + ], + "addressSpace": { + "addressPrefixes": "[parameters('addressPrefixes')]" + }, + "ddosProtectionPlan": "[if(not(empty(parameters('ddosProtectionPlanId'))), variables('ddosProtectionPlan'), null())]", + "dhcpOptions": "[if(not(empty(parameters('dnsServers'))), variables('dnsServers_var'), null())]", + "enableDdosProtection": "[not(empty(parameters('ddosProtectionPlanId')))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "virtualNetwork_subnets", + "count": "[length(parameters('subnets'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-subnet-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualNetworkName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('subnets')[copyIndex()].name]" + }, + "addressPrefix": { + "value": "[parameters('subnets')[copyIndex()].addressPrefix]" + }, + "addressPrefixes": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'addressPrefixes'), parameters('subnets')[copyIndex()].addressPrefixes, createArray())]" + }, + "applicationGatewayIpConfigurations": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'applicationGatewayIpConfigurations'), parameters('subnets')[copyIndex()].applicationGatewayIpConfigurations, createArray())]" + }, + "delegations": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'delegations'), parameters('subnets')[copyIndex()].delegations, createArray())]" + }, + "ipAllocations": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'ipAllocations'), parameters('subnets')[copyIndex()].ipAllocations, createArray())]" + }, + "natGatewayName": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'natGatewayName'), parameters('subnets')[copyIndex()].natGatewayName, '')]" + }, + "networkSecurityGroupName": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'networkSecurityGroupName'), parameters('subnets')[copyIndex()].networkSecurityGroupName, '')]" + }, + "networkSecurityGroupNameResourceGroupName": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'networkSecurityGroupNameResourceGroupName'), parameters('subnets')[copyIndex()].networkSecurityGroupNameResourceGroupName, resourceGroup().name)]" + }, + "privateEndpointNetworkPolicies": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'privateEndpointNetworkPolicies'), parameters('subnets')[copyIndex()].privateEndpointNetworkPolicies, '')]" + }, + "privateLinkServiceNetworkPolicies": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'privateLinkServiceNetworkPolicies'), parameters('subnets')[copyIndex()].privateLinkServiceNetworkPolicies, '')]" + }, + "routeTableName": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'routeTableName'), parameters('subnets')[copyIndex()].routeTableName, '')]" + }, + "serviceEndpointPolicies": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'serviceEndpointPolicies'), parameters('subnets')[copyIndex()].serviceEndpointPolicies, createArray())]" + }, + "serviceEndpoints": { + "value": "[if(contains(parameters('subnets')[copyIndex()], 'serviceEndpoints'), parameters('subnets')[copyIndex()].serviceEndpoints, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11921582790952761578" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Optional. The Name of the subnet resource." + } + }, + "virtualNetworkName": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent virtual network" + } + }, + "addressPrefix": { + "type": "string", + "metadata": { + "description": "Required. The address prefix for the subnet." + } + }, + "networkSecurityGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The network security group to assign to the subnet" + } + }, + "networkSecurityGroupNameResourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "minLength": 1, + "metadata": { + "description": "Optional. Resource Group where NSGs are deployed, if different than VNET Resource Group." + } + }, + "routeTableName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The route table to assign to the subnet" + } + }, + "routeTableResourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group where route table is deployed. " + } + }, + "serviceEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The service endpoints to enable on the subnet" + } + }, + "delegations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The delegations to enable on the subnet" + } + }, + "natGatewayName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the NAT Gateway to use for the subnet" + } + }, + "privateEndpointNetworkPolicies": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Disabled", + "Enabled", + "" + ], + "metadata": { + "description": "Optional. enable or disable apply network policies on private end point in the subnet." + } + }, + "privateLinkServiceNetworkPolicies": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Disabled", + "Enabled", + "" + ], + "metadata": { + "description": "Optional. enable or disable apply network policies on private link service in the subnet." + } + }, + "addressPrefixes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of address prefixes for the subnet." + } + }, + "applicationGatewayIpConfigurations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Application gateway IP configurations of virtual network resource." + } + }, + "ipAllocations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of IpAllocation which reference this subnet" + } + }, + "serviceEndpointPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of service endpoint policies." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedServiceEndpoints", + "count": "[length(parameters('serviceEndpoints'))]", + "input": { + "service": "[parameters('serviceEndpoints')[copyIndex('formattedServiceEndpoints')]]" + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('virtualNetworkName'), parameters('name'))]", + "properties": { + "addressPrefix": "[parameters('addressPrefix')]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupName'))), createObject('id', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('networkSecurityGroupNameResourceGroupName')), 'Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))), null())]", + "routeTable": "[if(not(empty(parameters('routeTableName'))), createObject('id', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, parameters('routeTableResourceGroupName')), 'Microsoft.Network/routeTables', parameters('routeTableName'))), null())]", + "natGateway": "[if(not(empty(parameters('natGatewayName'))), createObject('id', resourceId('Microsoft.Network/natGateways', parameters('natGatewayName'))), null())]", + "serviceEndpoints": "[if(not(empty(variables('formattedServiceEndpoints'))), variables('formattedServiceEndpoints'), createArray())]", + "delegations": "[parameters('delegations')]", + "privateEndpointNetworkPolicies": "[if(not(empty(parameters('privateEndpointNetworkPolicies'))), parameters('privateEndpointNetworkPolicies'), null())]", + "privateLinkServiceNetworkPolicies": "[if(not(empty(parameters('privateLinkServiceNetworkPolicies'))), parameters('privateLinkServiceNetworkPolicies'), null())]", + "addressPrefixes": "[parameters('addressPrefixes')]", + "applicationGatewayIpConfigurations": "[parameters('applicationGatewayIpConfigurations')]", + "ipAllocations": "[parameters('ipAllocations')]", + "serviceEndpointPolicies": "[parameters('serviceEndpointPolicies')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network peering was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network peering" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network peering" + } + }, + "subnetAddressPrefix": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))).addressPrefix]", + "metadata": { + "description": "The address prefix for the subnet" + } + }, + "subnetAddressPrefixes": { + "type": "array", + "value": "[if(not(empty(parameters('addressPrefixes'))), reference(resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('name'))).addressPrefixes, createArray())]", + "metadata": { + "description": "List of address prefixes for the subnet" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + }, + { + "copy": { + "name": "virtualNetwork_peering_local", + "count": "[length(parameters('virtualNetworkPeerings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-vNetPeering-local-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "localVnetName": { + "value": "[parameters('name')]" + }, + "remoteVirtualNetworkId": { + "value": "[parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId]" + }, + "name": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'name'), parameters('virtualNetworkPeerings')[copyIndex()].name, format('{0}-{1}', parameters('name'), last(split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/'))))]" + }, + "allowForwardedTraffic": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'allowForwardedTraffic'), parameters('virtualNetworkPeerings')[copyIndex()].allowForwardedTraffic, true())]" + }, + "allowGatewayTransit": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'allowGatewayTransit'), parameters('virtualNetworkPeerings')[copyIndex()].allowGatewayTransit, false())]" + }, + "allowVirtualNetworkAccess": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'allowVirtualNetworkAccess'), parameters('virtualNetworkPeerings')[copyIndex()].allowVirtualNetworkAccess, true())]" + }, + "doNotVerifyRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'doNotVerifyRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].doNotVerifyRemoteGateways, true())]" + }, + "useRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'useRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].useRemoteGateways, false())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "889026685906971683" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]", + "metadata": { + "description": "Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName" + } + }, + "localVnetName": { + "type": "string", + "metadata": { + "description": "Required. The Name of the Virtual Network to add the peering to." + } + }, + "remoteVirtualNetworkId": { + "type": "string", + "metadata": { + "description": "Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID" + } + }, + "allowForwardedTraffic": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true" + } + }, + "allowGatewayTransit": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false" + } + }, + "allowVirtualNetworkAccess": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true" + } + }, + "doNotVerifyRemoteGateways": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If we need to verify the provisioning state of the remote gateway. Default is true" + } + }, + "useRemoteGateways": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('localVnetName'), parameters('name'))]", + "properties": { + "allowForwardedTraffic": "[parameters('allowForwardedTraffic')]", + "allowGatewayTransit": "[parameters('allowGatewayTransit')]", + "allowVirtualNetworkAccess": "[parameters('allowVirtualNetworkAccess')]", + "doNotVerifyRemoteGateways": "[parameters('doNotVerifyRemoteGateways')]", + "useRemoteGateways": "[parameters('useRemoteGateways')]", + "remoteVirtualNetwork": { + "id": "[parameters('remoteVirtualNetworkId')]" + } + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network peering was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network peering" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/virtualNetworkPeerings', parameters('localVnetName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network peering" + } + } + } + } + }, + "dependsOn": [ + "virtualNetwork_subnets" + ] + }, + { + "condition": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringEnabled'), equals(parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringEnabled, true()), false())]", + "copy": { + "name": "virtualNetwork_peering_remote", + "count": "[length(parameters('virtualNetworkPeerings'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-vNetPeering-remote-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "subscriptionId": "[split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/')[2]]", + "resourceGroup": "[split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/')[4]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "localVnetName": { + "value": "[last(split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/'))]" + }, + "remoteVirtualNetworkId": { + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + }, + "name": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringName'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringName, format('{0}-{1}', last(split(parameters('virtualNetworkPeerings')[copyIndex()].remoteVirtualNetworkId, '/')), parameters('name')))]" + }, + "allowForwardedTraffic": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringAllowForwardedTraffic'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringAllowForwardedTraffic, true())]" + }, + "allowGatewayTransit": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringAllowGatewayTransit'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringAllowGatewayTransit, false())]" + }, + "allowVirtualNetworkAccess": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringAllowVirtualNetworkAccess'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringAllowVirtualNetworkAccess, true())]" + }, + "doNotVerifyRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringDoNotVerifyRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringDoNotVerifyRemoteGateways, true())]" + }, + "useRemoteGateways": { + "value": "[if(contains(parameters('virtualNetworkPeerings')[copyIndex()], 'remotePeeringUseRemoteGateways'), parameters('virtualNetworkPeerings')[copyIndex()].remotePeeringUseRemoteGateways, false())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "889026685906971683" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[format('{0}-{1}', parameters('localVnetName'), last(split(parameters('remoteVirtualNetworkId'), '/')))]", + "metadata": { + "description": "Optional. The Name of Vnet Peering resource. If not provided, default value will be localVnetName-remoteVnetName" + } + }, + "localVnetName": { + "type": "string", + "metadata": { + "description": "Required. The Name of the Virtual Network to add the peering to." + } + }, + "remoteVirtualNetworkId": { + "type": "string", + "metadata": { + "description": "Required. The Resource ID of the VNet that is this Local VNet is being peered to. Should be in the format of a Resource ID" + } + }, + "allowForwardedTraffic": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the forwarded traffic from the VMs in the local virtual network will be allowed/disallowed in remote virtual network. Default is true" + } + }, + "allowGatewayTransit": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If gateway links can be used in remote virtual networking to link to this virtual network. Default is false" + } + }, + "allowVirtualNetworkAccess": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Whether the VMs in the local virtual network space would be able to access the VMs in remote virtual network space. Default is true" + } + }, + "doNotVerifyRemoteGateways": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If we need to verify the provisioning state of the remote gateway. Default is true" + } + }, + "useRemoteGateways": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If remote gateways can be used on this virtual network. If the flag is set to true, and allowGatewayTransit on remote peering is also true, virtual network will use gateways of remote virtual network for transit. Only one peering can have this flag set to true. This flag cannot be set if virtual network already has a gateway. Default is false" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings", + "apiVersion": "2021-05-01", + "name": "[format('{0}/{1}', parameters('localVnetName'), parameters('name'))]", + "properties": { + "allowForwardedTraffic": "[parameters('allowForwardedTraffic')]", + "allowGatewayTransit": "[parameters('allowGatewayTransit')]", + "allowVirtualNetworkAccess": "[parameters('allowVirtualNetworkAccess')]", + "doNotVerifyRemoteGateways": "[parameters('doNotVerifyRemoteGateways')]", + "useRemoteGateways": "[parameters('useRemoteGateways')]", + "remoteVirtualNetwork": { + "id": "[parameters('remoteVirtualNetworkId')]" + } + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network peering was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network peering" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/virtualNetworkPeerings', parameters('localVnetName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network peering" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]", + "virtualNetwork_subnets" + ] + }, + { + "copy": { + "name": "virtualNetwork_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VNet-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2571696734351666513" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "SQL Managed Instance Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d')]", + "SQL Security Manager": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '056cd41c-7e88-42e1-933e-88ba6a50c9c3')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworks/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the virtual network was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]", + "metadata": { + "description": "The resource ID of the virtual network" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the virtual network" + } + }, + "subnetNames": { + "type": "array", + "copy": { + "count": "[length(parameters('subnets'))]", + "input": "[parameters('subnets')[copyIndex()].name]" + }, + "metadata": { + "description": "The names of the deployed subnets" + } + }, + "subnetResourceIds": { + "type": "array", + "copy": { + "count": "[length(parameters('subnets'))]", + "input": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('name'), parameters('subnets')[copyIndex()].name)]" + }, + "metadata": { + "description": "The resource IDs of the deployed subnets" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-ASG-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Network-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-NSG-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-UDR-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-WorkSpace-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdWorkSpaceName')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "appGroupResourceIds": { + "value": [ + "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-AppGroup-Desktop-{0}', parameters('time')))).outputs.resourceId.value]", + "[if(parameters('avdDeployRAppGroup'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-AppGroup-RApp-{0}', parameters('time')))).outputs.resourceId.value, '')]" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15216145002241656309" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the workspace to be attach to new Application Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "appGroupResourceIds": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Required. Resource IDs fo the existing Application groups this workspace will group together." + } + }, + "workspaceFriendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Workspace to be created." + } + }, + "workspaceDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Workspace to be created." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management", + "Feed" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management", + "Feed" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/workspaces", + "apiVersion": "2021-07-12", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "applicationGroupReferences": "[parameters('appGroupResourceIds')]", + "description": "[parameters('workspaceDescription')]", + "friendlyName": "[parameters('workspaceFriendlyName')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/workspaces/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/workspaces/{0}', parameters('name'))]", + "name": "[format('{0}-diagnosticsetting', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "workspace_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Workspace-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2283363463720322846" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization Workspace Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b')]", + "Desktop Virtualization Workspace Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/workspaces/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/workspaces', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD workspace" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD workspace was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD workspace" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-AppGroup-Desktop-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-AppGroup-RApp-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-ServiceObjects-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-HostPool-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdHostPoolName')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "hostpoolType": { + "value": "[parameters('avdHostPoolType')]" + }, + "startVMOnConnect": { + "value": "[parameters('avdStartVMOnConnect')]" + }, + "customRdpProperty": { + "value": "[parameters('avdHostPoolRdpProperty')]" + }, + "loadBalancerType": { + "value": "[parameters('avdHostPoolloadBalancerType')]" + }, + "maxSessionLimit": { + "value": "[parameters('avhHostPoolMaxSessions')]" + }, + "personalDesktopAssignmentType": { + "value": "[parameters('avdPersonalAssignType')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "6231831644454852626" + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Host Pool" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "hostpoolFriendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Host Pool to be created." + } + }, + "hostpoolDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Host Pool to be created." + } + }, + "hostpoolType": { + "type": "string", + "defaultValue": "Pooled", + "allowedValues": [ + "Personal", + "Pooled" + ], + "metadata": { + "description": "Optional. Set this parameter to Personal if you would like to enable Persistent Desktop experience. Defaults to Pooled." + } + }, + "personalDesktopAssignmentType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Automatic", + "Direct", + "" + ], + "metadata": { + "description": "Optional. Set the type of assignment for a Personal Host Pool type" + } + }, + "loadBalancerType": { + "type": "string", + "defaultValue": "BreadthFirst", + "allowedValues": [ + "BreadthFirst", + "DepthFirst", + "Persistent" + ], + "metadata": { + "description": "Optional. Type of load balancer algorithm." + } + }, + "maxSessionLimit": { + "type": "int", + "defaultValue": 99999, + "metadata": { + "description": "Optional. Maximum number of sessions." + } + }, + "customRdpProperty": { + "type": "string", + "defaultValue": "audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2;", + "metadata": { + "description": "Optional. Host Pool RDP properties" + } + }, + "validationEnviroment": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether to use validation enviroment. When set to true, the Host Pool will be deployed in a validation 'ring' (environment) that receives all the new features (might be less stable). Ddefaults to false that stands for the stable, production-ready environment." + } + }, + "vmTemplate": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The necessary information for adding more VMs to this Host Pool." + } + }, + "tokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. Host Pool token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the token will be valid for 8 hours." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "preferredAppGroupType": { + "type": "string", + "defaultValue": "Desktop", + "allowedValues": [ + "Desktop", + "None", + "RailApplications" + ], + "metadata": { + "description": "Optional. The type of preferred application group type, default to Desktop Application Group" + } + }, + "startVMOnConnect": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable Start VM on connect to allow users to start the virtual machine from a deallocated state. Important: Custom RBAC role required to power manage VMs." + } + }, + "validationEnvironment": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Validation host pool allows you to test service changes before they are deployed to production." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management", + "Connection", + "HostRegistration", + "AgentHealthStatus" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management", + "Connection", + "HostRegistration", + "AgentHealthStatus" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "tokenExpirationTime": "[dateTimeAdd(parameters('baseTime'), parameters('tokenValidityLength'))]" + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/hostPools", + "apiVersion": "2021-01-14-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "friendlyName": "[parameters('hostpoolFriendlyName')]", + "description": "[parameters('hostpoolDescription')]", + "hostPoolType": "[parameters('hostpoolType')]", + "customRdpProperty": "[parameters('customRdpProperty')]", + "personalDesktopAssignmentType": "[parameters('personalDesktopAssignmentType')]", + "preferredAppGroupType": "[parameters('preferredAppGroupType')]", + "maxSessionLimit": "[parameters('maxSessionLimit')]", + "loadBalancerType": "[parameters('loadBalancerType')]", + "validationEnviroment": "[parameters('validationEnviroment')]", + "startVMOnConnect": "[parameters('startVMOnConnect')]", + "validationEnvironment": "[parameters('validationEnvironment')]", + "registrationInfo": { + "expirationTime": "[variables('tokenExpirationTime')]", + "token": null, + "registrationTokenOperation": "Update" + }, + "vmTemplate": "[if(not(empty(parameters('vmTemplate'))), null(), string(parameters('vmTemplate')))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/hostPools/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/hostPools/{0}', parameters('name'))]", + "name": "[format('{0}-diagnosticsetting', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "hostPool_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-HostPool-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "5593527338932454557" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8')]", + "Desktop Virtualization Application Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Host Pool Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e307426c-f9b6-4e81-87de-d99efb3c32bc')]", + "Desktop Virtualization Host Pool Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ceadfde2-b300-400a-ab7b-6143895aa822')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization Session Host Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2ad6aaab-ead9-4eaa-8ac5-da422f562408')]", + "Desktop Virtualization User Session Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/hostPools/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD host pool" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD host pool was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD host pool" + } + }, + "hostPoolRestrationInfo": { + "type": "object", + "value": "[reference(resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('name'))).registrationInfo]" + }, + "tokenExpirationTime": { + "type": "string", + "value": "[dateTimeAdd(parameters('baseTime'), parameters('tokenValidityLength'))]", + "metadata": { + "description": "The expiration time for the registration token" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-ServiceObjects-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-AppGroup-Desktop-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdApplicationGroupNameDesktop')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "applicationGroupType": { + "value": "Desktop" + }, + "hostpoolName": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))).outputs.name.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17402173610326291522" + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Application Group to create this application in." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "applicationGroupType": { + "type": "string", + "allowedValues": [ + "RemoteApp", + "Desktop" + ], + "metadata": { + "description": "Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop" + } + }, + "hostpoolName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Host Pool to be linked to this Application Group." + } + }, + "friendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Application Group to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Application Group to be created." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of log analytics." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "applications": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of applications to be created in the Application Group." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/applicationGroups", + "apiVersion": "2021-07-12", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "hostPoolArmPath": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('hostpoolName'))]", + "friendlyName": "[parameters('friendlyName')]", + "description": "[parameters('description')]", + "applicationGroupType": "[parameters('applicationGroupType')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "appGroup_applications", + "count": "[length(parameters('applications'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppGroup-App-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('applications')[copyIndex()].name]" + }, + "appGroupName": { + "value": "[parameters('name')]" + }, + "description": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'description'), parameters('applications')[copyIndex()].description, '')]" + }, + "friendlyName": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'friendlyName'), parameters('applications')[copyIndex()].friendlyName, parameters('name'))]" + }, + "filePath": { + "value": "[parameters('applications')[copyIndex()].filePath]" + }, + "commandLineSetting": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'commandLineSetting'), parameters('applications')[copyIndex()].commandLineSetting, 'DoNotAllow')]" + }, + "commandLineArguments": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'commandLineArguments'), parameters('applications')[copyIndex()].commandLineArguments, '')]" + }, + "showInPortal": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'showInPortal'), parameters('applications')[copyIndex()].showInPortal, false())]" + }, + "iconPath": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'iconPath'), parameters('applications')[copyIndex()].iconPath, parameters('applications')[copyIndex()].filePath)]" + }, + "iconIndex": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'iconIndex'), parameters('applications')[copyIndex()].iconIndex, 0)]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10045431663420625657" + } + }, + "parameters": { + "appGroupName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application Group to create the application(s) in." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application to be created in the Application Group." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of Application.." + } + }, + "friendlyName": { + "type": "string", + "metadata": { + "description": "Required. Friendly name of Application.." + } + }, + "filePath": { + "type": "string", + "metadata": { + "description": "Required. Specifies a path for the executable file for the application." + } + }, + "commandLineSetting": { + "type": "string", + "defaultValue": "DoNotAllow", + "metadata": { + "description": "Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all." + }, + "allowedValues": [ + "Allow", + "DoNotAllow", + "Require" + ] + }, + "commandLineArguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-Line Arguments for Application." + } + }, + "showInPortal": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether to show the RemoteApp program in the RD Web Access server." + } + }, + "iconPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Path to icon." + } + }, + "iconIndex": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Index of the icon." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/applicationGroups/applications", + "apiVersion": "2021-07-12", + "name": "[format('{0}/{1}', parameters('appGroupName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "friendlyName": "[parameters('friendlyName')]", + "filePath": "[parameters('filePath')]", + "commandLineSetting": "[parameters('commandLineSetting')]", + "commandLineArguments": "[parameters('commandLineArguments')]", + "showInPortal": "[parameters('showInPortal')]", + "iconPath": "[parameters('iconPath')]", + "iconIndex": "[parameters('iconIndex')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "applicationResourceIds": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups/applications', parameters('appGroupName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed Application." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the AVD Application was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('appGroupName')]", + "metadata": { + "description": "The Name of the Application Group to register the Application in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "appGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppGroup-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "16979074209655907039" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8')]", + "Desktop Virtualization Application Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "Desktop Virtualization Workspace Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b')]", + "Desktop Virtualization Workspace Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD application group" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD application group was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD application group" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-ServiceObjects-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('avdDeployRAppGroup')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-AppGroup-RApp-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdApplicationGroupNameRApp')]" + }, + "location": { + "value": "[parameters('avdManagementPlaneLocation')]" + }, + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))).outputs.name.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17402173610326291522" + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Application Group to create this application in." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "applicationGroupType": { + "type": "string", + "allowedValues": [ + "RemoteApp", + "Desktop" + ], + "metadata": { + "description": "Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop" + } + }, + "hostpoolName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Host Pool to be linked to this Application Group." + } + }, + "friendlyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The friendly name of the Application Group to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the Application Group to be created." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of log analytics." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "Checkpoint", + "Error", + "Management" + ], + "allowedValues": [ + "Checkpoint", + "Error", + "Management" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "applications": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of applications to be created in the Application Group." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/applicationGroups", + "apiVersion": "2021-07-12", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "hostPoolArmPath": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('hostpoolName'))]", + "friendlyName": "[parameters('friendlyName')]", + "description": "[parameters('description')]", + "applicationGroupType": "[parameters('applicationGroupType')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "appGroup_applications", + "count": "[length(parameters('applications'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppGroup-App-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('applications')[copyIndex()].name]" + }, + "appGroupName": { + "value": "[parameters('name')]" + }, + "description": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'description'), parameters('applications')[copyIndex()].description, '')]" + }, + "friendlyName": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'friendlyName'), parameters('applications')[copyIndex()].friendlyName, parameters('name'))]" + }, + "filePath": { + "value": "[parameters('applications')[copyIndex()].filePath]" + }, + "commandLineSetting": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'commandLineSetting'), parameters('applications')[copyIndex()].commandLineSetting, 'DoNotAllow')]" + }, + "commandLineArguments": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'commandLineArguments'), parameters('applications')[copyIndex()].commandLineArguments, '')]" + }, + "showInPortal": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'showInPortal'), parameters('applications')[copyIndex()].showInPortal, false())]" + }, + "iconPath": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'iconPath'), parameters('applications')[copyIndex()].iconPath, parameters('applications')[copyIndex()].filePath)]" + }, + "iconIndex": { + "value": "[if(contains(parameters('applications')[copyIndex()], 'iconIndex'), parameters('applications')[copyIndex()].iconIndex, 0)]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10045431663420625657" + } + }, + "parameters": { + "appGroupName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application Group to create the application(s) in." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application to be created in the Application Group." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of Application.." + } + }, + "friendlyName": { + "type": "string", + "metadata": { + "description": "Required. Friendly name of Application.." + } + }, + "filePath": { + "type": "string", + "metadata": { + "description": "Required. Specifies a path for the executable file for the application." + } + }, + "commandLineSetting": { + "type": "string", + "defaultValue": "DoNotAllow", + "metadata": { + "description": "Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all." + }, + "allowedValues": [ + "Allow", + "DoNotAllow", + "Require" + ] + }, + "commandLineArguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-Line Arguments for Application." + } + }, + "showInPortal": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether to show the RemoteApp program in the RD Web Access server." + } + }, + "iconPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Path to icon." + } + }, + "iconIndex": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Index of the icon." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/applicationGroups/applications", + "apiVersion": "2021-07-12", + "name": "[format('{0}/{1}', parameters('appGroupName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "friendlyName": "[parameters('friendlyName')]", + "filePath": "[parameters('filePath')]", + "commandLineSetting": "[parameters('commandLineSetting')]", + "commandLineArguments": "[parameters('commandLineArguments')]", + "showInPortal": "[parameters('showInPortal')]", + "iconPath": "[parameters('iconPath')]", + "iconIndex": "[parameters('iconIndex')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "applicationResourceIds": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups/applications', parameters('appGroupName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed Application." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the AVD Application was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('appGroupName')]", + "metadata": { + "description": "The Name of the Application Group to register the Application in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + }, + { + "copy": { + "name": "appGroup_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AppGroup-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "16979074209655907039" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ca6382a4-1721-4bcf-a114-ff0c70227b6b')]", + "Desktop Virtualization Application Group Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '86240b0e-9422-4c43-887b-b61143f32ba8')]", + "Desktop Virtualization Application Group Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55')]", + "Desktop Virtualization Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '082f0a83-3be5-4ba1-904c-961cca79b387')]", + "Desktop Virtualization Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '49a72310-ab8d-41df-bbb0-79b649203868')]", + "Desktop Virtualization User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63')]", + "Desktop Virtualization Workspace Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21efdde3-836f-432b-bf3d-3e8e734d4b2b')]", + "Desktop Virtualization Workspace Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]", + "metadata": { + "description": "The resource ID of the AVD application group" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the AVD application group was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the AVD application group" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-ServiceObjects-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createStartVmOnConnectCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Start-VM-on-Connect-Role-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdWrklSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "subscriptionId": { + "value": "[variables('avdWrklSubscriptionId')]" + }, + "description": { + "value": "Start VM on connect AVD" + }, + "roleName": { + "value": "StartVMonConnect-AVD" + }, + "actions": { + "value": [ + "Microsoft.Compute/virtualMachines/start/action", + "Microsoft.Compute/virtualMachines/*/read" + ] + }, + "assignableScopes": { + "value": [ + "[format('/subscriptions/{0}', variables('avdWrklSubscriptionId'))]" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11581817901689295753" + } + }, + "parameters": { + "roleName": { + "type": "string", + "metadata": { + "description": "Required. Name of the custom RBAC role to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the custom RBAC role to be created." + } + }, + "actions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed actions." + } + }, + "notActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied actions." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "notDataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "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." + } + }, + "assignableScopes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Role definition assignable scopes. If not provided, will use the current scope provided." + } + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2018-01-01-preview", + "name": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "properties": { + "roleName": "[parameters('roleName')]", + "description": "[parameters('description')]", + "type": "customRole", + "permissions": [ + { + "actions": "[parameters('actions')]", + "notActions": "[parameters('notActions')]", + "dataActions": "[parameters('dataActions')]", + "notDataActions": "[parameters('notDataActions')]" + } + ], + "assignableScopes": "[if(not(empty(parameters('assignableScopes'))), parameters('assignableScopes'), array(subscription().id))]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "metadata": { + "description": "The GUID of the Role Definition" + } + }, + "scope": { + "type": "string", + "value": "[subscription().id]", + "metadata": { + "description": "The scope this Role Definition applies to" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Authorization/roleDefinitions', guid(parameters('roleName'), parameters('subscriptionId')))]", + "metadata": { + "description": "The resource ID of the Role Definition" + } + } + } + } + } + }, + { + "condition": "[parameters('createAibCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Azure-Image-Builder-Role-{0}', parameters('time'))]", + "subscriptionId": "[variables('avdShrdlSubscriptionId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "subscriptionId": { + "value": "[variables('avdShrdlSubscriptionId')]" + }, + "description": { + "value": "Azure Image Builder AVD" + }, + "roleName": { + "value": "AzureImageBuilder-AVD" + }, + "actions": { + "value": [ + "Microsoft.Authorization/*/read", + "Microsoft.Compute/images/write", + "Microsoft.Compute/images/read", + "Microsoft.Compute/images/delete", + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read", + "Microsoft.Compute/galleries/images/versions/read", + "Microsoft.Compute/galleries/images/versions/write", + "Microsoft.Storage/storageAccounts/blobServices/containers/read", + "Microsoft.Storage/storageAccounts/blobServices/containers/write", + "Microsoft.Storage/storageAccounts/blobServices/read", + "Microsoft.ContainerInstance/containerGroups/read", + "Microsoft.ContainerInstance/containerGroups/write", + "Microsoft.ContainerInstance/containerGroups/start/action", + "Microsoft.ManagedIdentity/userAssignedIdentities/*/read", + "Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action", + "Microsoft.Authorization/*/read", + "Microsoft.Resources/deployments/*", + "Microsoft.Resources/deploymentScripts/read", + "Microsoft.Resources/deploymentScripts/write", + "Microsoft.Resources/subscriptions/resourceGroups/read", + "Microsoft.VirtualMachineImages/imageTemplates/run/action", + "Microsoft.VirtualMachineImages/imageTemplates/read", + "Microsoft.Network/virtualNetworks/read", + "Microsoft.Network/virtualNetworks/subnets/join/action" + ] + }, + "assignableScopes": { + "value": [ + "[format('/subscriptions/{0}', variables('avdShrdlSubscriptionId'))]" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11581817901689295753" + } + }, + "parameters": { + "roleName": { + "type": "string", + "metadata": { + "description": "Required. Name of the custom RBAC role to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the custom RBAC role to be created." + } + }, + "actions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed actions." + } + }, + "notActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied actions." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "notDataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes" + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "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." + } + }, + "assignableScopes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Role definition assignable scopes. If not provided, will use the current scope provided." + } + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2018-01-01-preview", + "name": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "properties": { + "roleName": "[parameters('roleName')]", + "description": "[parameters('description')]", + "type": "customRole", + "permissions": [ + { + "actions": "[parameters('actions')]", + "notActions": "[parameters('notActions')]", + "dataActions": "[parameters('dataActions')]", + "notDataActions": "[parameters('notDataActions')]" + } + ], + "assignableScopes": "[if(not(empty(parameters('assignableScopes'))), parameters('assignableScopes'), array(subscription().id))]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('roleName'), parameters('subscriptionId'))]", + "metadata": { + "description": "The GUID of the Role Definition" + } + }, + "scope": { + "type": "string", + "value": "[subscription().id]", + "metadata": { + "description": "The scope this Role Definition applies to" + } + }, + "resourceId": { + "type": "string", + "value": "[subscriptionResourceId(parameters('subscriptionId'), 'Microsoft.Authorization/roleDefinitions', guid(parameters('roleName'), parameters('subscriptionId')))]", + "metadata": { + "description": "The resource ID of the Role Definition" + } + } + } + } + } + }, + { + "condition": "[parameters('createAibManagedIdentity')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('image-Builder-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('aibManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2573176279193711763" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10301210696081621096" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "clientId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).clientId]", + "metadata": { + "description": "The client ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('useSharedImage')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('deployment-Script-Managed-Identity-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('deployScriptManagedIdentityName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2573176279193711763" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2018-11-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "userMsi_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-UserMSI-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10301210696081621096" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the user assigned identity" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]", + "metadata": { + "description": "The resource ID of the user assigned identity" + } + }, + "principalId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).principalId]", + "metadata": { + "description": "The principal ID of the user assigned identity" + } + }, + "clientId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))).clientId]", + "metadata": { + "description": "The client ID of the user assigned identity" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the user assigned identity was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[or(parameters('useSharedImage'), parameters('createAibManagedIdentity'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-userManagedIdentityDelay-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('AVD-userManagedIdentityDelay-{0}', parameters('time'))]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT10M" + }, + "scriptContent": { + "value": "[if(or(parameters('useSharedImage'), parameters('createAibManagedIdentity')), ' Write-Host \"Start\"\r\n Get-Date\r\n Start-Sleep -Seconds 60\r\n Write-Host \"Stop\"\r\n Get-Date\r\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10579853314175634433" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT6H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "condition": "[and(parameters('createAibCustomRole'), parameters('createAibManagedIdentity'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Azure-Image-Builder-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createAibCustomRole'), reference(subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))).outputs.resourceId.value, '')]" + }, + "principalId": { + "value": "[if(parameters('createAibManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))).outputs.principalId.value, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15079652935768304950" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-userManagedIdentityDelay-{0}', parameters('time')))]" + ] + }, + { + "condition": "[and(parameters('createAibCustomRole'), parameters('useSharedImage'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('deploy-script-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createAibCustomRole'), reference(subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))).outputs.resourceId.value, format('/subscriptions/{0}/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830', variables('avdShrdlSubscriptionId')))]" + }, + "principalId": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))).outputs.principalId.value, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15079652935768304950" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-Role-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-userManagedIdentityDelay-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('createStartVmOnConnectCustomRole')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Start-VM-OnConnect-RoleAssign-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleDefinitionIdOrName": { + "value": "[if(parameters('createStartVmOnConnectCustomRole'), reference(subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('Start-VM-on-Connect-Role-{0}', parameters('time')))).outputs.resourceId.value, '')]" + }, + "principalId": { + "value": "[parameters('avdEnterpriseAppObjectId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15079652935768304950" + } + }, + "parameters": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "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'" + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)" + } + }, + "resourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of role assignment" + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the delegated managed identity resource" + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to" + } + }, + "conditionVersion": { + "type": "string", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition. Currently accepted value is \"2.0\"" + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered." + } + } + }, + "variables": { + "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", + "AcrPull": "/providers/Microsoft.Authorization/roleDefinitions/7f951dda-4ed3-4680-a7ca-43fe172d538d", + "AcrImageSigner": "/providers/Microsoft.Authorization/roleDefinitions/6cef56e8-d556-48e5-a04f-b8e64114680f", + "AcrDelete": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "AcrQuarantineReader": "/providers/Microsoft.Authorization/roleDefinitions/cdda3590-29a3-44f6-95f2-9f980659eb04", + "AcrQuarantineWriter": "/providers/Microsoft.Authorization/roleDefinitions/c8d4ff99-41c3-41a8-9f60-21dfdad59608", + "API Management Service Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/e022efe7-f5ba-4159-bbe4-b44f577e9b61", + "API Management Service Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/71522526-b88f-4d52-b57f-d31fc3546d0d", + "Application Insights Component Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ae349356-3a1b-4a5e-921d-050484c6347e", + "Application Insights Snapshot Debugger": "/providers/Microsoft.Authorization/roleDefinitions/08954f03-6346-4c2e-81c0-ec3a5cfae23b", + "Attestation Reader": "/providers/Microsoft.Authorization/roleDefinitions/fd1bd22b-8476-40bc-a0bc-69b95687b9f3", + "Automation Job Operator": "/providers/Microsoft.Authorization/roleDefinitions/4fe576fe-1146-4730-92eb-48519fa6bf9f", + "Automation Runbook Operator": "/providers/Microsoft.Authorization/roleDefinitions/5fb5aef8-1081-4b8e-bb16-9d5d0385bab5", + "Automation Operator": "/providers/Microsoft.Authorization/roleDefinitions/d3881f73-407a-4167-8283-e981cbba0404", + "Avere Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4f8fab4f-1852-4a58-a46a-8eaf358af14a", + "Avere Operator": "/providers/Microsoft.Authorization/roleDefinitions/c025889f-8102-4ebf-b32c-fc0c6f0c6bd9", + "Azure Kubernetes Service Cluster Admin Role": "/providers/Microsoft.Authorization/roleDefinitions/0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8", + "Azure Kubernetes Service Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/4abbcc35-e782-43d8-92c5-2d3f1bd2253f", + "Azure Maps Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/423170ca-a8f6-4b0f-8487-9e4eb8f49bfa", + "Azure Stack Registration Owner": "/providers/Microsoft.Authorization/roleDefinitions/6f12a6df-dd06-4f3e-bcb1-ce8be600526a", + "Backup Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e467623-bb1f-42f4-a55d-6e525e11384b", + "Billing Reader": "/providers/Microsoft.Authorization/roleDefinitions/fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64", + "Backup Operator": "/providers/Microsoft.Authorization/roleDefinitions/00c29273-979b-4161-815c-10b084fb9324", + "Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912", + "BizTalk Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5e3c6656-6cfa-4708-81fe-0de47ac73342", + "CDN Endpoint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/426e0c7f-0c7e-4658-b36f-ff54d6c29b45", + "CDN Endpoint Reader": "/providers/Microsoft.Authorization/roleDefinitions/871e35f6-b5c1-49cc-a043-bde969a0f2cd", + "CDN Profile Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ec156ff8-a8d1-4d15-830c-5b80698ca432", + "CDN Profile Reader": "/providers/Microsoft.Authorization/roleDefinitions/8f96442b-4075-438f-813d-ad51ab4019af", + "Classic Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b34d265f-36f7-4a0d-a4d4-e158ca92e90f", + "Classic Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86e8f5dc-a6e9-4c67-9d15-de283e8eac25", + "Classic Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/985d6b00-f706-48f5-a6fe-d0ca12fb668d", + "ClearDB MySQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9106cda0-8a86-4e81-b686-29a22c54effe", + "Classic Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/d73bb868-a0df-4d4d-bd69-98a00b01fccb", + "Cognitive Services User": "/providers/Microsoft.Authorization/roleDefinitions/a97b65f3-24c7-4388-baec-2e87135dc908", + "Cognitive Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68", + "CosmosBackupOperator": "/providers/Microsoft.Authorization/roleDefinitions/db7b14f2-5adf-42da-9f96-f2ee17bab5cb", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Cosmos DB Account Reader Role": "/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", + "Cost Management Contributor": "/providers/Microsoft.Authorization/roleDefinitions/434105ed-43f6-45c7-a02f-909b2ba83430", + "Cost Management Reader": "/providers/Microsoft.Authorization/roleDefinitions/72fafb9e-0641-4937-9268-a91bfd8191a3", + "Data Box Contributor": "/providers/Microsoft.Authorization/roleDefinitions/add466c9-e687-43fc-8d98-dfcf8d720be5", + "Data Box Reader": "/providers/Microsoft.Authorization/roleDefinitions/028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027", + "Data Factory Contributor": "/providers/Microsoft.Authorization/roleDefinitions/673868aa-7521-48a0-acc6-0f60742d39f5", + "Data Purger": "/providers/Microsoft.Authorization/roleDefinitions/150f5e0c-0603-4f03-8c7f-cf70034c4e90", + "Data Lake Analytics Developer": "/providers/Microsoft.Authorization/roleDefinitions/47b7735b-770e-4598-a7da-8b91488b4c88", + "DevTest Labs User": "/providers/Microsoft.Authorization/roleDefinitions/76283e04-6283-4c54-8f91-bcf1374a3c64", + "DocumentDB Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5bd9cd88-fe45-4216-938b-f97437e15450", + "DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/befefa01-2a29-4197-83a8-272ff33ce314", + "EventGrid EventSubscription Contributor": "/providers/Microsoft.Authorization/roleDefinitions/428e0ff0-5e57-4d9c-a221-2c70d0e0a443", + "EventGrid EventSubscription Reader": "/providers/Microsoft.Authorization/roleDefinitions/2414bbcf-6497-4faf-8c65-045460748405", + "Graph Owner": "/providers/Microsoft.Authorization/roleDefinitions/b60367af-1334-4454-b71e-769d9a4f83d9", + "HDInsight Domain Services Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8d8d5a11-05d3-4bda-a417-a08778121c7c", + "Intelligent Systems Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/03a6d094-3444-4b3d-88af-7477090a9e5e", + "Key Vault Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f25e0fa2-a7c8-4377-a976-54943a77a395", + "Knowledge Consumer": "/providers/Microsoft.Authorization/roleDefinitions/ee361c5d-f7b5-4119-b4b6-892157c8f64c", + "Lab Creator": "/providers/Microsoft.Authorization/roleDefinitions/b97fb8bc-a8b2-4522-a38b-dd33c7e65ead", + "Log Analytics Reader": "/providers/Microsoft.Authorization/roleDefinitions/73c42c96-874c-492b-b04d-ab87d138a893", + "Log Analytics Contributor": "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293", + "Logic App Operator": "/providers/Microsoft.Authorization/roleDefinitions/515c2055-d9d4-4321-b1b9-bd0c9a0f79fe", + "Logic App Contributor": "/providers/Microsoft.Authorization/roleDefinitions/87a39d53-fc1b-424a-814c-f7e04687dc9e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44", + "Managed Identity Operator": "/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830", + "Managed Identity Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e40ec5ca-96e0-45a2-b4ff-59039f2c2b59", + "Management Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c", + "Management Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/ac63b705-f282-497d-ac71-919bf39d939d", + "Monitoring Metrics Publisher": "/providers/Microsoft.Authorization/roleDefinitions/3913510d-42f4-4e42-8a64-420c390055eb", + "Monitoring Reader": "/providers/Microsoft.Authorization/roleDefinitions/43d0d8ad-25c7-4714-9337-8ba259a9fe05", + "Network Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7", + "Monitoring Contributor": "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "New Relic APM Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5d28c62d-5b37-4476-8438-e587778df237", + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Redis Cache Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e0f68234-74aa-48ed-b826-c38b57376e17", + "Reader and Data Access": "/providers/Microsoft.Authorization/roleDefinitions/c12c1c16-33a1-487b-954d-41c89c60f349", + "Resource Policy Contributor": "/providers/Microsoft.Authorization/roleDefinitions/36243c78-bf99-498c-9df9-86d9f8d28608", + "Scheduler Job Collections Contributor": "/providers/Microsoft.Authorization/roleDefinitions/188a0f2f-5c9e-469b-ae67-2aa5ce574b94", + "Search Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7ca78c08-252a-4471-8644-bb5ff32d4ba0", + "Security Admin": "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd", + "Security Reader": "/providers/Microsoft.Authorization/roleDefinitions/39bc4728-0917-49c7-9d2c-d95423bc2eb4", + "Spatial Anchors Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827", + "Site Recovery Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6670b86e-a3f7-4917-ac9b-5d6ab1be4567", + "Site Recovery Operator": "/providers/Microsoft.Authorization/roleDefinitions/494ae006-db33-4328-bf46-533a6560a3ca", + "Spatial Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/5d51204f-eb77-4b1c-b86a-2ec626c49413", + "Site Recovery Reader": "/providers/Microsoft.Authorization/roleDefinitions/dbaa88c4-0c30-4179-9fb3-46319faa6149", + "Spatial Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/70bbe301-9835-447d-afdd-19eb3167307c", + "SQL Managed Instance Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4939a1f6-9ae0-4e48-a1e0-f2cbe897382d", + "SQL DB Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9b7fa17d-e63e-47b0-bb0a-15c516ac86ec", + "SQL Security Manager": "/providers/Microsoft.Authorization/roleDefinitions/056cd41c-7e88-42e1-933e-88ba6a50c9c3", + "Storage Account Contributor": "/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab", + "SQL Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437", + "Storage Account Key Operator Service Role": "/providers/Microsoft.Authorization/roleDefinitions/81a9662b-bebf-436f-a333-f67b29880f12", + "Storage Blob Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe", + "Storage Blob Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "Storage Blob Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/2a2b9908-6ea1-4ae2-8e65-a410df84e7d1", + "Storage Queue Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/974c5e8b-45b9-4653-ba55-5f855dd0fb88", + "Storage Queue Data Message Processor": "/providers/Microsoft.Authorization/roleDefinitions/8a0f0c08-91a1-4084-bc3d-661d67233fed", + "Storage Queue Data Message Sender": "/providers/Microsoft.Authorization/roleDefinitions/c6a89b2d-59bc-44d0-9896-0f6e12d7b80a", + "Storage Queue Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/19e7f393-937e-4f77-808e-94535e297925", + "Support Request Contributor": "/providers/Microsoft.Authorization/roleDefinitions/cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e", + "Traffic Manager Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a4b10055-b0c7-44c2-b00f-c7b5b3550cf7", + "Virtual Machine Administrator Login": "/providers/Microsoft.Authorization/roleDefinitions/1c0163c0-47e6-4577-8991-ea5c82e286e4", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Virtual Machine User Login": "/providers/Microsoft.Authorization/roleDefinitions/fb879df8-f326-4884-b1cf-06f3ad86be52", + "Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c", + "Web Plan Contributor": "/providers/Microsoft.Authorization/roleDefinitions/2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b", + "Website Contributor": "/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772", + "Azure Service Bus Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/090c5cfd-751d-490a-894a-3ce6f1109419", + "Azure Event Hubs Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/f526a384-b230-433a-b45c-95f59c4a2dec", + "Attestation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/bbf86eb8-f7b4-4cce-96e4-18cddf81d86e", + "HDInsight Cluster Operator": "/providers/Microsoft.Authorization/roleDefinitions/61ed4efc-fab3-44fd-b111-e24485cc132a", + "Cosmos DB Operator": "/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa", + "Hybrid Server Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/48b40c6e-82e0-4eb3-90d5-19e40f49b624", + "Hybrid Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb", + "Azure Event Hubs Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/a638d3c7-ab3a-418d-83e6-5f17a39d4fde", + "Azure Event Hubs Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/2b629674-e913-4c01-ae53-ef4638d8f975", + "Azure Service Bus Data Receiver": "/providers/Microsoft.Authorization/roleDefinitions/4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0", + "Azure Service Bus Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/69a216fc-b8fb-44d8-bc22-1f3c2cd27a39", + "Storage File Data SMB Share Reader": "/providers/Microsoft.Authorization/roleDefinitions/aba4ae5f-2193-4029-9191-0cb91df5e314", + "Storage File Data SMB Share Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb", + "Private DNS Zone Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b12aa53e-6015-4669-85d0-8515ebb3ae7f", + "Storage Blob Delegator": "/providers/Microsoft.Authorization/roleDefinitions/db58b8e5-c6ad-4a2a-8342-4190687cbf4a", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Storage File Data SMB Share Elevated Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a7264617-510b-434b-a828-9731dc254ea7", + "Blueprint Contributor": "/providers/Microsoft.Authorization/roleDefinitions/41077137-e803-4205-871c-5a86e6a753b4", + "Blueprint Operator": "/providers/Microsoft.Authorization/roleDefinitions/437d2ced-4a38-4302-8479-ed2bcb43d090", + "Azure Sentinel Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ab8e14d6-4a74-4a29-9ba8-549422addade", + "Azure Sentinel Responder": "/providers/Microsoft.Authorization/roleDefinitions/3e150937-b8fe-4cfb-8069-0eaf05ecd056", + "Azure Sentinel Reader": "/providers/Microsoft.Authorization/roleDefinitions/8d289c81-5878-46d4-8554-54e1e3d8b5cb", + "Workbook Reader": "/providers/Microsoft.Authorization/roleDefinitions/b279062a-9be3-42a0-92ae-8b3cf002ec4d", + "Workbook Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e8ddcd69-c73f-4f9f-9844-4100522f16ad", + "SignalR AccessKey Reader": "/providers/Microsoft.Authorization/roleDefinitions/04165923-9d83-45d5-8227-78b77b0a687e", + "SignalR/Web PubSub Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761", + "Azure Connected Machine Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/b64e21ea-ac4e-4cdf-9dc9-5b892992bee7", + "Azure Connected Machine Resource Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cd570a14-e51a-42ad-bac8-bafd67325302", + "Managed Services Registration assignment Delete Role": "/providers/Microsoft.Authorization/roleDefinitions/91c1777a-f3dc-4fae-b103-61d183457e46", + "App Configuration Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b", + "App Configuration Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071", + "Kubernetes Cluster - Azure Arc Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/34e09817-6cbe-4d01-b1a2-e0eac5743d41", + "Experimentation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a22b-edd6ce5c915c", + "Cognitive Services QnA Maker Reader": "/providers/Microsoft.Authorization/roleDefinitions/466ccd10-b268-4a11-b098-b4849f024126", + "Cognitive Services QnA Maker Editor": "/providers/Microsoft.Authorization/roleDefinitions/f4cc2bf9-21be-47a1-bdf1-5c5804381025", + "Experimentation Administrator": "/providers/Microsoft.Authorization/roleDefinitions/7f646f1b-fa08-80eb-a33b-edd6ce5c915c", + "Remote Rendering Administrator": "/providers/Microsoft.Authorization/roleDefinitions/3df8b902-2a6f-47c7-8cc5-360e9b272a7e", + "Remote Rendering Client": "/providers/Microsoft.Authorization/roleDefinitions/d39065c4-c120-43c9-ab0a-63eed9795f0a", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Security Assessment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/612c2aa1-cb24-443b-ac28-3ab7272de6f5", + "Tag Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f", + "Integration Service Environment Developer": "/providers/Microsoft.Authorization/roleDefinitions/c7aa55d3-1abb-444a-a5ca-5e51e485d6ec", + "Integration Service Environment Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a41e2c5b-bd99-4a07-88f4-9bf657a760b8", + "Azure Kubernetes Service Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8", + "Azure Digital Twins Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/d57506d4-4c8d-48b1-8587-93c323f6a5a3", + "Azure Digital Twins Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/bcd981a7-7f74-457b-83e1-cceb9e632ffe", + "Hierarchy Settings Administrator": "/providers/Microsoft.Authorization/roleDefinitions/350f8d15-c687-4448-8ae1-157740a3936d", + "FHIR Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/5a1fc7df-4bf1-4951-a576-89034ee01acd", + "FHIR Data Exporter": "/providers/Microsoft.Authorization/roleDefinitions/3db33094-8700-4567-8da5-1501d4e7e843", + "FHIR Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/4c8d0bbc-75d3-4935-991f-5f3c56d81508", + "FHIR Data Writer": "/providers/Microsoft.Authorization/roleDefinitions/3f88fce4-5892-4214-ae73-ba5294559913", + "Experimentation Reader": "/providers/Microsoft.Authorization/roleDefinitions/49632ef5-d9ac-41f4-b8e7-bbe587fa74a1", + "Object Understanding Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/4dd61c23-6743-42fe-a388-d8bdd41cb745", + "Azure Maps Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204", + "Cognitive Services Custom Vision Contributor": "/providers/Microsoft.Authorization/roleDefinitions/c1ff6cc2-c111-46fe-8896-e0ef812ad9f3", + "Cognitive Services Custom Vision Deployment": "/providers/Microsoft.Authorization/roleDefinitions/5c4089e1-6d96-4d2f-b296-c1bc7137275f", + "Cognitive Services Custom Vision Labeler": "/providers/Microsoft.Authorization/roleDefinitions/88424f51-ebe7-446f-bc41-7fa16989e96c", + "Cognitive Services Custom Vision Reader": "/providers/Microsoft.Authorization/roleDefinitions/93586559-c37d-4a6b-ba08-b9f0940c2d73", + "Cognitive Services Custom Vision Trainer": "/providers/Microsoft.Authorization/roleDefinitions/0a5ae4ab-0d65-4eeb-be61-29fc9b54394b", + "Key Vault Administrator": "/providers/Microsoft.Authorization/roleDefinitions/00482a5a-887f-4fb3-b363-3b7fe8e74483", + "Key Vault Crypto Officer": "/providers/Microsoft.Authorization/roleDefinitions/14b46e9e-c2b7-41b4-b07b-48a6ebf60603", + "Key Vault Crypto User": "/providers/Microsoft.Authorization/roleDefinitions/12338af0-0e69-4776-bea7-57ae8d297424", + "Key Vault Secrets Officer": "/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7", + "Key Vault Secrets User": "/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6", + "Key Vault Certificates Officer": "/providers/Microsoft.Authorization/roleDefinitions/a4417e6f-fecd-4de8-b567-7b0420556985", + "Key Vault Reader": "/providers/Microsoft.Authorization/roleDefinitions/21090545-7ca7-4776-b22c-e363652d74d2", + "Key Vault Crypto Service Encryption User": "/providers/Microsoft.Authorization/roleDefinitions/e147488a-f6f5-4113-8e2d-b22465e65bf6", + "Azure Arc Kubernetes Viewer": "/providers/Microsoft.Authorization/roleDefinitions/63f0a09d-1495-4db4-a681-037d84835eb4", + "Azure Arc Kubernetes Writer": "/providers/Microsoft.Authorization/roleDefinitions/5b999177-9696-4545-85c7-50de3797e5a1", + "Azure Arc Kubernetes Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/8393591c-06b9-48a2-a542-1bd6b377f6a2", + "Azure Arc Kubernetes Admin": "/providers/Microsoft.Authorization/roleDefinitions/dffb1e0c-446f-4dde-a09f-99eb5cc68b96", + "Azure Kubernetes Service RBAC Cluster Admin": "/providers/Microsoft.Authorization/roleDefinitions/b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b", + "Azure Kubernetes Service RBAC Admin": "/providers/Microsoft.Authorization/roleDefinitions/3498e952-d568-435e-9b2c-8d77e338d7f7", + "Azure Kubernetes Service RBAC Reader": "/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", + "Azure Kubernetes Service RBAC Writer": "/providers/Microsoft.Authorization/roleDefinitions/a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb", + "Services Hub Operator": "/providers/Microsoft.Authorization/roleDefinitions/82200a5b-e217-47a5-b665-6d8765ee745b", + "Object Understanding Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/d18777c0-1514-4662-8490-608db7d334b6", + "Azure Arc Enabled Kubernetes Cluster User Role": "/providers/Microsoft.Authorization/roleDefinitions/00493d72-78f6-4148-b6c5-d3ce8e4799dd", + "SignalR REST API Owner": "/providers/Microsoft.Authorization/roleDefinitions/fd53cd77-2268-407a-8f46-7e7863d0f521", + "Collaborative Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/daa9e50b-21df-454c-94a6-a8050adab352", + "Device Update Reader": "/providers/Microsoft.Authorization/roleDefinitions/e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f", + "Device Update Administrator": "/providers/Microsoft.Authorization/roleDefinitions/02ca0879-e8e4-47a5-a61e-5c618b76e64a", + "Device Update Content Administrator": "/providers/Microsoft.Authorization/roleDefinitions/0378884a-3af5-44ab-8323-f5b22f9f3c98", + "Device Update Deployments Administrator": "/providers/Microsoft.Authorization/roleDefinitions/e4237640-0e3d-4a46-8fda-70bc94856432", + "Device Update Deployments Reader": "/providers/Microsoft.Authorization/roleDefinitions/49e2f5d2-7741-4835-8efa-19e1fe35e47f", + "Device Update Content Reader": "/providers/Microsoft.Authorization/roleDefinitions/d1ee9a80-8b14-47f0-bdc2-f4a351625a7b", + "Cognitive Services Metrics Advisor Administrator": "/providers/Microsoft.Authorization/roleDefinitions/cb43c632-a144-4ec5-977c-e80c4affc34a", + "Cognitive Services Metrics Advisor User": "/providers/Microsoft.Authorization/roleDefinitions/3b20f47b-3825-43cb-8114-4bd2201156a8", + "AgFood Platform Service Reader": "/providers/Microsoft.Authorization/roleDefinitions/7ec7ccdc-f61e-41fe-9aaf-980df0a44eba", + "AgFood Platform Service Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8508508a-4469-4e45-963b-2518ee0bb728", + "AgFood Platform Service Admin": "/providers/Microsoft.Authorization/roleDefinitions/f8da80de-1ff9-4747-ad80-a19b7f6079e3", + "Managed HSM contributor": "/providers/Microsoft.Authorization/roleDefinitions/18500a29-7fe2-46b2-a342-b16a415e101d", + "Security Detonation Chamber Submitter": "/providers/Microsoft.Authorization/roleDefinitions/0b555d9b-b4a7-4f43-b330-627f0e5be8f0", + "SignalR REST API Reader": "/providers/Microsoft.Authorization/roleDefinitions/ddde6b66-c0df-4114-a159-3618637b3035", + "SignalR Service Owner": "/providers/Microsoft.Authorization/roleDefinitions/7e4f1700-ea5a-4f59-8f37-079cfe29dce3", + "Reservation Purchaser": "/providers/Microsoft.Authorization/roleDefinitions/f7b75c60-3036-4b75-91c3-6b41c27c1689", + "Storage Account Backup Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1", + "Experimentation Metric Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6188b7c9-7d01-4f99-a59f-c88b630326c0", + "Project Babylon Data Curator": "/providers/Microsoft.Authorization/roleDefinitions/9ef4ef9c-a049-46b0-82ab-dd8ac094c889", + "Project Babylon Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/c8d896ba-346d-4f50-bc1d-7d1c84130446", + "Project Babylon Data Source Administrator": "/providers/Microsoft.Authorization/roleDefinitions/05b7651b-dc44-475e-b74d-df3db49fae0f", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Disk Backup Reader": "/providers/Microsoft.Authorization/roleDefinitions/3e5e47e6-65f7-47ef-90b5-e5dd4d455f24", + "Disk Restore Operator": "/providers/Microsoft.Authorization/roleDefinitions/b50d9833-a0cb-478e-945f-707fcc997c13", + "Disk Snapshot Contributor": "/providers/Microsoft.Authorization/roleDefinitions/7efff54f-a5b4-42b5-a1c5-5411624893ce", + "Microsoft.Kubernetes connected cluster role": "/providers/Microsoft.Authorization/roleDefinitions/5548b2cf-c94c-4228-90ba-30851930a12f", + "Security Detonation Chamber Submission Manager": "/providers/Microsoft.Authorization/roleDefinitions/a37b566d-3efa-4beb-a2f2-698963fa42ce", + "Security Detonation Chamber Publisher": "/providers/Microsoft.Authorization/roleDefinitions/352470b3-6a9c-4686-b503-35deb827e500", + "Collaborative Runtime Operator": "/providers/Microsoft.Authorization/roleDefinitions/7a6f0e70-c033-4fb1-828c-08514e5f4102", + "CosmosRestoreOperator": "/providers/Microsoft.Authorization/roleDefinitions/5432c526-bc82-444a-b7ba-57c5b0b5b34f", + "FHIR Data Converter": "/providers/Microsoft.Authorization/roleDefinitions/a1705bd2-3a8f-45a5-8683-466fcfd5cc24", + "Azure Sentinel Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f4c81013-99ee-4d62-a7ee-b3f1f648599a", + "Quota Request Operator": "/providers/Microsoft.Authorization/roleDefinitions/0e5f05e5-9ab9-446b-b98d-1e2157c94125", + "EventGrid Contributor": "/providers/Microsoft.Authorization/roleDefinitions/1e241071-0855-49ea-94dc-649edcd759de", + "Security Detonation Chamber Reader": "/providers/Microsoft.Authorization/roleDefinitions/28241645-39f8-410b-ad48-87863e2951d5", + "Object Anchors Account Reader": "/providers/Microsoft.Authorization/roleDefinitions/4a167cdf-cb95-4554-9203-2347fe489bd9", + "Object Anchors Account Owner": "/providers/Microsoft.Authorization/roleDefinitions/ca0835dd-bacc-42dd-8ed2-ed5e7230d15b", + "WorkloadBuilder Migration Agent Role": "/providers/Microsoft.Authorization/roleDefinitions/d17ce0a2-0697-43bc-aac5-9113337ab61c", + "Azure Spring Cloud Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b5537268-8956-4941-a8f0-646150406f0c", + "Cognitive Services Speech User": "/providers/Microsoft.Authorization/roleDefinitions/f2dc8367-1007-4938-bd23-fe263f013447", + "Cognitive Services Speech Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0e75ca1e-0464-4b4d-8b93-68208a576181", + "Cognitive Services Face Recognizer": "/providers/Microsoft.Authorization/roleDefinitions/9894cab4-e18a-44aa-828b-cb588cd6f2d7", + "Media Services Account Administrator": "/providers/Microsoft.Authorization/roleDefinitions/054126f8-9a2b-4f1c-a9ad-eca461f08466", + "Media Services Live Events Administrator": "/providers/Microsoft.Authorization/roleDefinitions/532bc159-b25e-42c0-969e-a1d439f60d77", + "Media Services Media Operator": "/providers/Microsoft.Authorization/roleDefinitions/e4395492-1534-4db2-bedf-88c14621589c", + "Media Services Policy Administrator": "/providers/Microsoft.Authorization/roleDefinitions/c4bba371-dacd-4a26-b320-7250bca963ae", + "Media Services Streaming Endpoints Administrator": "/providers/Microsoft.Authorization/roleDefinitions/99dba123-b5fe-44d5-874c-ced7199a5804", + "Stream Analytics Query Tester": "/providers/Microsoft.Authorization/roleDefinitions/1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf", + "AnyBuild Builder": "/providers/Microsoft.Authorization/roleDefinitions/a2138dac-4907-4679-a376-736901ed8ad8", + "IoT Hub Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/b447c946-2db7-41ec-983d-d8bf3b1c77e3", + "IoT Hub Twin Contributor": "/providers/Microsoft.Authorization/roleDefinitions/494bdba2-168f-4f31-a0a1-191d2f7c028c", + "IoT Hub Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4ea46cd5-c1b2-4a8e-910b-273211f9ce47", + "IoT Hub Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/4fc6c259-987e-4a07-842e-c321cc9d413f", + "Test Base Reader": "/providers/Microsoft.Authorization/roleDefinitions/15e0f5a1-3450-4248-8e25-e2afe88a9e85", + "Search Index Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/1407120a-92aa-4202-b7e9-c0e197c71c8f", + "Search Index Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/8ebe5a00-799e-43f5-93ac-243d3dce84a7", + "Storage Table Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/76199698-9eea-4c19-bc75-cec21354c6b6", + "Storage Table Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3", + "DICOM Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a", + "DICOM Data Owner": "/providers/Microsoft.Authorization/roleDefinitions/58a3b984-7adf-4c20-983a-32417c86fbc8", + "EventGrid Data Sender": "/providers/Microsoft.Authorization/roleDefinitions/d5a91429-5739-47e2-a06b-3470a27159e7", + "Disk Pool Operator": "/providers/Microsoft.Authorization/roleDefinitions/60fc6e62-5479-42d4-8bf4-67625fcc2840", + "AzureML Data Scientist": "/providers/Microsoft.Authorization/roleDefinitions/f6c7c914-8db3-469d-8ca1-694a8f32e121", + "Grafana Admin": "/providers/Microsoft.Authorization/roleDefinitions/22926164-76b3-42b3-bc55-97df8dab3e41", + "Azure Connected SQL Server Onboarding": "/providers/Microsoft.Authorization/roleDefinitions/e8113dce-c529-4d33-91fa-e9b972617508", + "Azure Relay Sender": "/providers/Microsoft.Authorization/roleDefinitions/26baccc8-eea7-41f1-98f4-1762cc7f685d", + "Azure Relay Owner": "/providers/Microsoft.Authorization/roleDefinitions/2787bf04-f1f5-4bfe-8383-c8a24483ee38", + "Azure Relay Listener": "/providers/Microsoft.Authorization/roleDefinitions/26e0b698-aa6d-4085-9386-aadae190014d", + "Grafana Viewer": "/providers/Microsoft.Authorization/roleDefinitions/60921a7e-fef1-4a43-9b16-a26c52ad4769", + "Grafana Editor": "/providers/Microsoft.Authorization/roleDefinitions/a79a5197-3a5c-4973-a920-486035ffd60f", + "Automation Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f353d9bd-d4a6-484e-a77a-8050b599b867", + "Kubernetes Extension Contributor": "/providers/Microsoft.Authorization/roleDefinitions/85cb6faf-e071-4c9b-8136-154b5a04f717", + "Device Provisioning Service Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/10745317-c249-44a1-a5ce-3a4353c0bbd8", + "Device Provisioning Service Data Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dfce44e4-17b7-4bd1-a6d1-04996ec95633", + "CodeSigning Certificate Profile Signer": "/providers/Microsoft.Authorization/roleDefinitions/2837e146-70d7-4cfd-ad55-7efa6464f958", + "Azure Spring Cloud Service Registry Reader": "/providers/Microsoft.Authorization/roleDefinitions/cff1b556-2399-4e7e-856d-a8f754be7b65", + "Azure Spring Cloud Service Registry Contributor": "/providers/Microsoft.Authorization/roleDefinitions/f5880b48-c26d-48be-b172-7927bfa1c8f1", + "Azure Spring Cloud Config Server Reader": "/providers/Microsoft.Authorization/roleDefinitions/d04c6db6-4947-4782-9e91-30a88feb7be7", + "Azure Spring Cloud Config Server Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a06f5c24-21a7-4e1a-aa2b-f19eb6684f5b", + "Azure VM Managed identities restore Contributor": "/providers/Microsoft.Authorization/roleDefinitions/6ae96244-5829-4925-a7d3-5975537d91dd", + "Azure Maps Search and Render Data Reader": "/providers/Microsoft.Authorization/roleDefinitions/6be48352-4f82-47c9-ad5e-0acacefdb005", + "Azure Maps Contributor": "/providers/Microsoft.Authorization/roleDefinitions/dba33070-676a-4fb0-87fa-064dc56ff7fb" + }, + "roleDefinitionId_var": "[if(contains(variables('builtInRoleNames_var'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames_var')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "name": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "properties": { + "roleDefinitionId": "[variables('roleDefinitionId_var')]", + "principalId": "[parameters('principalId')]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId'))]", + "metadata": { + "description": "The GUID of the Role Assignment" + } + }, + "scope": { + "type": "string", + "value": "[resourceGroup().id]", + "metadata": { + "description": "The resource ID of the Role Assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId(parameters('resourceGroupName'), 'Microsoft.Authorization/roleAssignments', guid(parameters('subscriptionId'), parameters('resourceGroupName'), variables('roleDefinitionId_var'), parameters('principalId')))]", + "metadata": { + "description": "The scope this Role Assignment applies to" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the role assignment was applied at" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-ServiceObjects-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('Start-VM-on-Connect-Role-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('useSharedImage')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-Azure-Compute-Gallery-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('imageGalleryName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "galleryDescription": { + "value": "Azure Virtual Desktops Images" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2946734335041369354" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + }, + "minLength": 1 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the Azure Shared Image Gallery" + } + }, + "images": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Images to create" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/galleries", + "apiVersion": "2020-09-30", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "description": "[parameters('galleryDescription')]", + "identifier": {} + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "gallery_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Gallery-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7239157228659163859" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + }, + { + "copy": { + "name": "galleries_images", + "count": "[length(parameters('images'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Gallery-Image-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('images')[copyIndex()].name]" + }, + "galleryName": { + "value": "[parameters('name')]" + }, + "osType": { + "value": "[if(contains(parameters('images')[copyIndex()], 'osType'), parameters('images')[copyIndex()].osType, 'Windows')]" + }, + "osState": { + "value": "[if(contains(parameters('images')[copyIndex()], 'osState'), parameters('images')[copyIndex()].osState, 'Generalized')]" + }, + "publisher": { + "value": "[if(contains(parameters('images')[copyIndex()], 'publisher'), parameters('images')[copyIndex()].publisher, 'MicrosoftWindowsServer')]" + }, + "offer": { + "value": "[if(contains(parameters('images')[copyIndex()], 'offer'), parameters('images')[copyIndex()].offer, 'WindowsServer')]" + }, + "sku": { + "value": "[if(contains(parameters('images')[copyIndex()], 'sku'), parameters('images')[copyIndex()].sku, '2019-Datacenter')]" + }, + "minRecommendedvCPUs": { + "value": "[if(contains(parameters('images')[copyIndex()], 'minRecommendedvCPUs'), parameters('images')[copyIndex()].minRecommendedvCPUs, 1)]" + }, + "maxRecommendedvCPUs": { + "value": "[if(contains(parameters('images')[copyIndex()], 'maxRecommendedvCPUs'), parameters('images')[copyIndex()].maxRecommendedvCPUs, 4)]" + }, + "minRecommendedMemory": { + "value": "[if(contains(parameters('images')[copyIndex()], 'minRecommendedMemory'), parameters('images')[copyIndex()].minRecommendedMemory, 4)]" + }, + "maxRecommendedMemory": { + "value": "[if(contains(parameters('images')[copyIndex()], 'maxRecommendedMemory'), parameters('images')[copyIndex()].maxRecommendedMemory, 16)]" + }, + "hyperVGeneration": { + "value": "[if(contains(parameters('images')[copyIndex()], 'hyperVGeneration'), parameters('images')[copyIndex()].hyperVGeneration, 'V1')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('images')[copyIndex()], 'roleAssignments'), parameters('images')[copyIndex()].roleAssignments, createArray())]" + }, + "tags": { + "value": "[if(contains(parameters('images')[copyIndex()], 'tags'), parameters('images')[copyIndex()].tags, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7394022970317708952" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + } + }, + "osType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "WindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "2019-Datacenter", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2020-09-30", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "galleryImage_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7663380971783417430" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "myCustomRoleAtSub": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the image" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the image" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed image gallery" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed image gallery" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed image gallery" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('useSharedImage')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "galleryName": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))).outputs.name.value, '')]" + }, + "name": { + "value": "[variables('imageDefinitionsTemSpecName')]" + }, + "osState": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osState]" + }, + "osType": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osType]" + }, + "publisher": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].publisher]" + }, + "offer": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].offer]" + }, + "sku": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].sku]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "hyperVGeneration": { + "value": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].hyperVGeneration]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7394022970317708952" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Shared Image Gallery" + } + }, + "osType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "WindowsServer", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "2019-Datacenter", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "maxValue": 128, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "maxValue": 4000, + "minValue": 1, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only. - V1 or V2" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2020-09-30", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "galleryImage_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7663380971783417430" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "myCustomRoleAtSub": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60cb79d9-783a-50a4-9f05-d4c579fb8ce3')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image was deployed into" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the image" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the image" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('useSharedImage')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Deploy-Image-Template-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('imageDefinitionsTemSpecName')]" + }, + "userMsiName": { + "value": "[if(and(parameters('createAibManagedIdentity'), parameters('useSharedImage')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))).outputs.name.value, '')]" + }, + "userMsiResourceGroup": { + "value": "[if(and(parameters('createAibManagedIdentity'), parameters('useSharedImage')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))).outputs.resourceGroupName.value, '')]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "imageReplicationRegions": { + "value": "[if(equals(parameters('avdSessionHostLocation'), parameters('aiblocation')), array(format('{0}', parameters('avdSessionHostLocation'))), concat(array(format('{0}', parameters('aiblocation'))), array(format('{0}', parameters('avdSessionHostLocation')))))]" + }, + "sigImageDefinitionId": { + "value": "[if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))).outputs.resourceId.value, '')]" + }, + "vmSize": { + "value": "[variables('imageVmSize')]" + }, + "customizationSteps": { + "value": [ + { + "type": "PowerShell", + "name": "OptimizeOS", + "runElevated": true, + "runAsSystem": true, + "scriptUri": "[format('{0}Scripts/Optimize_OS_for_AVD.ps1', variables('baseScriptUri'))]" + }, + { + "type": "WindowsRestart", + "restartCheckCommand": "write-host \"restarting post Optimizations\"", + "restartTimeout": "10m" + }, + { + "type": "WindowsUpdate", + "searchCriteria": "IsInstalled=0", + "filters": [ + "exclude:$_.Title -like '*Preview*'", + "include:$true" + ], + "updateLimit": 40 + }, + { + "type": "PowerShell", + "name": "Sleep for a min", + "runElevated": true, + "runAsSystem": true, + "inline": [ + "Write-Host \"Sleep for a 5 min\" ", + "Start-Sleep -Seconds 300" + ] + }, + { + "type": "WindowsRestart", + "restartCheckCommand": "write-host \"restarting post Windows updates\"", + "restartTimeout": "10m" + }, + { + "type": "PowerShell", + "name": "Sleep for a min", + "runElevated": true, + "runAsSystem": true, + "inline": [ + "Write-Host \"Sleep for a min\" ", + "Start-Sleep -Seconds 60" + ] + }, + { + "type": "WindowsRestart", + "restartTimeout": "10m" + } + ] + }, + "imageSource": { + "value": { + "type": "PlatformImage", + "publisher": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].publisher]", + "offer": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].offer]", + "sku": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].sku]", + "osAccountType": "[variables('avdOsImageDefinitions')[parameters('avdOsImage')].osAccountType]", + "version": "latest" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17771597006127176971" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Image Template to be built by the Azure Image Builder service." + } + }, + "userMsiName": { + "type": "string", + "metadata": { + "description": "Required. Name of the User Assigned Identity to be used to deploy Image Templates in Azure Image Builder." + } + }, + "userMsiResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the user assigned identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "buildTimeoutInMinutes": { + "type": "int", + "defaultValue": 0, + "maxValue": 960, + "minValue": 0, + "metadata": { + "description": "Optional. Image build timeout in minutes. Allowed values: 0-960. 0 means the default 240 minutes" + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_D2s_v3", + "metadata": { + "description": "Optional. Specifies the size for the VM." + } + }, + "osDiskSizeGB": { + "type": "int", + "defaultValue": 128, + "metadata": { + "description": "Optional. Specifies the size of OS disk." + } + }, + "subnetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of an already existing subnet, e.g. '/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/'. If no value is provided, a new VNET will be created in the target Resource Group." + } + }, + "imageSource": { + "type": "object", + "metadata": { + "description": "Required. Image source definition in object format." + } + }, + "customizationSteps": { + "type": "array", + "metadata": { + "description": "Required. Customization steps to be run when building the VM image." + } + }, + "managedImageName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the managed image that will be created in the AIB resourcegroup." + } + }, + "unManagedImageName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the unmanaged image that will be created in the AIB resourcegroup." + } + }, + "sigImageDefinitionId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of Shared Image Gallery to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/" + } + }, + "imageReplicationRegions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of the regions the image produced by this solution should be stored in the Shared Image Gallery. When left empty, the deployment's location will be taken as a default value." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a unique image template name." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "variables": { + "managedImageName_var": "[format('{0}-{1}', parameters('managedImageName'), parameters('baseTime'))]", + "managedImageId": "[format('/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/images/{2}', subscription().subscriptionId, resourceGroup().name, variables('managedImageName_var'))]", + "imageReplicationRegions_var": "[if(empty(parameters('imageReplicationRegions')), array(parameters('location')), parameters('imageReplicationRegions'))]", + "managedImage": { + "type": "ManagedImage", + "imageId": "[variables('managedImageId')]", + "location": "[parameters('location')]", + "runOutputName": "[format('{0}-ManagedImage', variables('managedImageName_var'))]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + } + }, + "conditionalManagedImage": "[if(empty(parameters('managedImageName')), createArray(), array(variables('managedImage')))]", + "sharedImage": { + "type": "SharedImage", + "galleryImageId": "[parameters('sigImageDefinitionId')]", + "runOutputName": "[if(not(empty(parameters('sigImageDefinitionId'))), format('{0}-SharedImage', split(parameters('sigImageDefinitionId'), '/')[10]), 'SharedImage')]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + }, + "replicationRegions": "[variables('imageReplicationRegions_var')]" + }, + "conditionalSharedImage": "[if(empty(parameters('sigImageDefinitionId')), createArray(), array(variables('sharedImage')))]", + "unManagedImage": { + "type": "VHD", + "runOutputName": "[format('{0}-VHD', parameters('unManagedImageName'))]", + "artifactTags": { + "sourceType": "[parameters('imageSource').type]", + "sourcePublisher": "[if(contains(parameters('imageSource'), 'publisher'), parameters('imageSource').publisher, null())]", + "sourceOffer": "[if(contains(parameters('imageSource'), 'offer'), parameters('imageSource').offer, null())]", + "sourceSku": "[if(contains(parameters('imageSource'), 'sku'), parameters('imageSource').sku, null())]", + "sourceVersion": "[if(contains(parameters('imageSource'), 'version'), parameters('imageSource').version, null())]", + "sourceImageId": "[if(contains(parameters('imageSource'), 'imageId'), parameters('imageSource').imageId, null())]", + "sourceImageVersionID": "[if(contains(parameters('imageSource'), 'imageVersionID'), parameters('imageSource').imageVersionID, null())]", + "creationTime": "[parameters('baseTime')]" + } + }, + "conditionalUnManagedImage": "[if(empty(parameters('unManagedImageName')), createArray(), array(variables('unManagedImage')))]", + "distribute": "[concat(variables('conditionalManagedImage'), variables('conditionalSharedImage'), variables('conditionalUnManagedImage'))]", + "vnetConfig": { + "subnetId": "[parameters('subnetId')]" + } + }, + "resources": [ + { + "type": "Microsoft.VirtualMachineImages/imageTemplates", + "apiVersion": "2020-02-14", + "name": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', resourceId(parameters('userMsiResourceGroup'), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userMsiName')))]": {} + } + }, + "properties": { + "buildTimeoutInMinutes": "[parameters('buildTimeoutInMinutes')]", + "vmProfile": { + "vmSize": "[parameters('vmSize')]", + "osDiskSizeGB": "[parameters('osDiskSizeGB')]", + "vnetConfig": "[if(not(empty(parameters('subnetId'))), variables('vnetConfig'), null())]" + }, + "source": "[parameters('imageSource')]", + "customize": "[parameters('customizationSteps')]", + "distribute": "[variables('distribute')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", + "name": "[format('{0}-{1}-lock', format('{0}-{1}', parameters('name'), parameters('baseTime')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "imageTemplate_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-ImageTemplate-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "18274597265899808015" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", + "metadata": { + "description": "The resource ID of the image template" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the image template was deployed into" + } + }, + "name": { + "type": "string", + "value": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", + "metadata": { + "description": "The name of the image template" + } + }, + "runThisCommand": { + "type": "string", + "value": "[format('Invoke-AzResourceAction -ResourceName {0} -ResourceGroupName {1} -ResourceType Microsoft.VirtualMachineImages/imageTemplates -Action Run -Force', format('{0}-{1}', parameters('name'), parameters('baseTime')), resourceGroup().name)]", + "metadata": { + "description": "The command to run in order to trigger the image build" + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-Azure-Compute-Gallery-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('useSharedImage')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Build-Image-Template-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('imageTemplateBuildName-{0}', parameters('avdOsImage'))]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "timeout": { + "value": "PT2H" + }, + "containerGroupName": { + "value": "[format('imageTemplateBuildName-{0}-aci', parameters('avdOsImage'))]" + }, + "userAssignedIdentities": { + "value": "[if(parameters('createAibManagedIdentity'), createObject(format('{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))).outputs.resourceId.value), createObject()), createObject())]" + }, + "arguments": { + "value": "[format('-subscriptionId ''{0}'' -resourceGroupName ''{1}'' -imageTemplateName ''{2}''', variables('avdShrdlSubscriptionId'), variables('avdSharedResourcesRgName'), if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))).outputs.name.value, null()))]" + }, + "scriptContent": { + "value": "[if(parameters('useSharedImage'), ' param(\r\n [string] [Parameter(Mandatory=$true)] $resourceGroupName,\r\n [string] [Parameter(Mandatory=$true)] $imageTemplateName,\r\n [string] [Parameter(Mandatory=$true)] $subscriptionId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n Install-Module -Name Az.ImageBuilder -Force\r\n # Kick off the Azure Image Build \r\n Write-Host \"Kick off Image buld for $imageTemplateName\"\r\n Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $resourceGroupName -ResourceType \"Microsoft.VirtualMachineImages/imageTemplates\" -Action Run -Force \r\n $DeploymentScriptOutputs = @{}\r\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\r\n $status=$getStatus.LastRunStatusRunState\r\n $statusMessage=$getStatus.LastRunStatusMessage\r\n $startTime=Get-Date\r\n $reset=$startTime + (New-TimeSpan -Minutes 40)\r\n Write-Host \"Script will time out in $reset\"\r\n do {\r\n $now=Get-Date\r\n Write-Host \"Getting the current time: $now\"\r\n if (($now -eq $reset) -or ($now -gt $reset)) {\r\n break\r\n }\r\n $expiryTime=(Get-AzAccessToken).ExpiresOn.Datetime\r\n Write-Host \"Token expiry time is $expiryTime\"\r\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\r\n $status=$getStatus.LastRunStatusRunState\r\n Write-Host \"Current status of the image build $imageTemplateName is: $status\"\r\n Write-Host \"Script will time out in $reset\"\r\n $DeploymentScriptOutputs=$now\r\n $DeploymentScriptOutputs=$status\r\n if ($status -eq \"Failed\") {\r\n Write-Host \"Build failed for image template: $imageTemplateName. Check the Packer logs\"\r\n $DeploymentScriptOutputs=\"Build Failed\"\r\n throw \"Build Failed\"\r\n }\r\n if (($status -eq \"Canceled\") -or ($status -eq \"Canceling\") ) {\r\n Write-Host \"User canceled the build. Delete the Image template definition: $imageTemplateName\"\r\n throw \"User canceled the build.\"\r\n }\r\n if ($status -eq \"Succeeded\") {\r\n Write-Host \"Success. Image template definition: $imageTemplateName is finished \"\r\n break\r\n }\r\n }\r\n until (($now -eq $reset) -or ($now -gt $reset))\r\n Write-Host \"Finished check for image build status at $now\"\r\n\r\n\r\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10579853314175634433" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT6H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('image-Builder-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('useSharedImage')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Build-Image-Template-{0}-Check-Build', parameters('avdOsImage'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('imageTemplateBuildCheckName-{0}', parameters('avdOsImage'))]" + }, + "location": { + "value": "[parameters('aiblocation')]" + }, + "timeout": { + "value": "PT30M" + }, + "containerGroupName": { + "value": "[format('imageTemplateBuildCheckName-{0}-aci', parameters('avdOsImage'))]" + }, + "runOnce": { + "value": false + }, + "azPowerShellVersion": { + "value": "6.2" + }, + "cleanupPreference": { + "value": "Always" + }, + "userAssignedIdentities": { + "value": "[if(parameters('useSharedImage'), createObject(format('{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))).outputs.resourceId.value), createObject()), createObject())]" + }, + "arguments": { + "value": "[format('-subscriptionId ''{0}'' -resourceGroupName ''{1}'' -imageTemplateName ''{2}''', variables('avdShrdlSubscriptionId'), variables('avdSharedResourcesRgName'), if(parameters('useSharedImage'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))).outputs.name.value, null()))]" + }, + "scriptContent": { + "value": "[if(parameters('useSharedImage'), ' param(\r\n [string] [Parameter(Mandatory=$true)] $resourceGroupName,\r\n [string] [Parameter(Mandatory=$true)] $imageTemplateName,\r\n [string] [Parameter(Mandatory=$true)] $subscriptionId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n Install-Module -Name Az.ImageBuilder -Force\r\n $DeploymentScriptOutputs = @{}\r\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\r\n $status=$getStatus.LastRunStatusRunState\r\n $statusMessage=$getStatus.LastRunStatusMessage\r\n $startTime=Get-Date\r\n $reset=$startTime + (New-TimeSpan -Minutes 40)\r\n Write-Host \"Script will time out in $reset\"\r\n do {\r\n $now=Get-Date\r\n Write-Host \"Getting the current time: $now\"\r\n if (($now -eq $reset) -or ($now -gt $reset)) {\r\n break\r\n }\r\n $expiryTime=(Get-AzAccessToken).ExpiresOn.Datetime\r\n Write-Host \"Token expiry time is $expiryTime\"\r\n $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)\r\n $status=$getStatus.LastRunStatusRunState\r\n Write-Host \"Current status of the image build $imageTemplateName is: $status\"\r\n Write-Host \"Script will time out in $reset\"\r\n $DeploymentScriptOutputs=$now\r\n $DeploymentScriptOutputs=$status\r\n if ($status -eq \"Failed\") {\r\n Write-Host \"Build failed for image template: $imageTemplateName. Check the Packer logs\"\r\n $DeploymentScriptOutputs=\"Build Failed\"\r\n throw \"Build Failed\"\r\n }\r\n if (($status -eq \"Canceled\") -or ($status -eq \"Canceling\") ) {\r\n Write-Host \"User canceled the build. Delete the Image template definition: $imageTemplateName\"\r\n throw \"User canceled the build.\"\r\n }\r\n if ($status -eq \"Succeeded\") {\r\n Write-Host \"Success. Image template definition: $imageTemplateName is finished \"\r\n break\r\n }\r\n }\r\n until (($now -eq $reset) -or ($now -gt $reset))\r\n Write-Host \"Finished check for image build status at $now\"\r\n\r\n ', '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10579853314175634433" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Display name of the script to be run." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzurePowerShell", + "allowedValues": [ + "AzurePowerShell", + "AzureCLI" + ], + "metadata": { + "description": "Optional. Type of the script. AzurePowerShell, AzureCLI." + } + }, + "azPowerShellVersion": { + "type": "string", + "defaultValue": "3.0", + "metadata": { + "description": "Optional. Azure PowerShell module version to be used." + } + }, + "azCliVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Azure CLI module version to be used." + } + }, + "scriptContent": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead." + } + }, + "primaryScriptUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead." + } + }, + "environmentVariables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The environment variables to pass over to the script. Must have a 'name' and a 'value' or a 'secretValue' property." + } + }, + "supportingScriptUris": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of supporting files for the external script (defined in primaryScriptUri). Does not work with internal scripts (code defined in scriptContent)." + } + }, + "arguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-line arguments to pass to the script. Arguments are separated by spaces." + } + }, + "retentionInterval": { + "type": "string", + "defaultValue": "P1D", + "metadata": { + "description": "Optional. Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week)." + } + }, + "runOnce": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. When set to false, script will run every time the template is deployed. When set to true, the script will only run once." + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "Always", + "allowedValues": [ + "Always", + "OnSuccess", + "OnExpiration" + ], + "metadata": { + "description": "Optional. The clean up preference when the script execution gets in a terminal state. Specify the preference on when to delete the deployment script resources. The default value is Always, which means the deployment script resources are deleted despite the terminal state (Succeeded, Failed, canceled)." + } + }, + "containerGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Container group name, if not specified then the name will get auto-generated. Not specifying a 'containerGroupName' indicates the system to generate a unique name which might end up flagging an Azure Policy as non-compliant. Use 'containerGroupName' when you have an Azure Policy that expects a specific naming convention or when you want to fully control the name. 'containerGroupName' property must be between 1 and 63 characters long, must contain only lowercase letters, numbers, and dashes and it cannot start or end with a dash and consecutive dashes are not allowed." + } + }, + "timeout": { + "type": "string", + "defaultValue": "PT6H", + "metadata": { + "description": "Optional. Maximum allowed script execution time specified in ISO 8601 format. Default value is PT1H - 1 hour; 'PT30M' - 30 minutes; 'P5D' - 5 days; 'P1Y' 1 year." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to make sure the script run every time the template is deployed." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "containerSettings": { + "containerGroupName": "[parameters('containerGroupName')]" + }, + "identityType": "[if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None')]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[parameters('kind')]", + "properties": { + "azPowerShellVersion": "[if(equals(parameters('kind'), 'AzurePowerShell'), parameters('azPowerShellVersion'), null())]", + "azCliVersion": "[if(equals(parameters('kind'), 'AzureCLI'), parameters('azCliVersion'), null())]", + "containerSettings": "[if(empty(parameters('containerGroupName')), null(), variables('containerSettings'))]", + "arguments": "[parameters('arguments')]", + "environmentVariables": "[if(empty(parameters('environmentVariables')), null(), parameters('environmentVariables'))]", + "scriptContent": "[if(empty(parameters('scriptContent')), null(), parameters('scriptContent'))]", + "primaryScriptUri": "[if(empty(parameters('primaryScriptUri')), null(), parameters('primaryScriptUri'))]", + "supportingScriptUris": "[if(empty(parameters('supportingScriptUris')), null(), parameters('supportingScriptUris'))]", + "cleanupPreference": "[parameters('cleanupPreference')]", + "forceUpdateTag": "[if(parameters('runOnce'), resourceGroup().name, parameters('baseTime'))]", + "retentionInterval": "[parameters('retentionInterval')]", + "timeout": "[parameters('timeout')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Resources/deploymentScripts/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Resources/deploymentScripts', parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployment script" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the deployment script was deployed into" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployment script" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Azure-Image-Builder-RoleAssign-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('deployment-Script-Managed-Identity-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Deploy-Image-Template-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Build-Image-Template-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Workload-KeyVault-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdServiceObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdWrklKvName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "enableRbacAuthorization": { + "value": false + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "[if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time')))).outputs.resourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId'))]", + "service": "vault" + } + ] + }, + "secrets": { + "value": { + "secureList": [ + { + "name": "avdVmLocalUserPassword", + "value": "[parameters('avdVmLocalUserPassword')]", + "contentType": "Session host local user credentials" + }, + { + "name": "avdVmLocalUserName", + "value": "[parameters('avdVmLocalUserName')]", + "contentType": "Session host local user credentials" + }, + { + "name": "avdDomainJoinUserName", + "value": "[parameters('avdDomainJoinUserName')]", + "contentType": "Domain join credentials" + }, + { + "name": "avdDomainJoinUserPassword", + "value": "[parameters('avdDomainJoinUserPassword')]", + "contentType": "Domain join credentials" + } + ] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4895311282793848977" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "maxLength": 24, + "metadata": { + "description": "Optional. Name of the Key Vault. If no name is provided, then unique name will be created." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of access policies object" + } + }, + "secrets": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. All secrets to create" + } + }, + "keys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. All keys to create" + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute" + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment" + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios." + } + }, + "enableSoftDelete": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "defaultValue": 90, + "metadata": { + "description": "Optional. softDelete data retention days. It accepts >=7 and <=90." + } + }, + "enableRbacAuthorization": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC." + } + }, + "createMode": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "vaultSku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault" + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "vNetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. " + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "AuditEvent" + ], + "allowedValues": [ + "AuditEvent" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(if(contains(parameters('networkAcls'), 'virtualNetworkRules'), parameters('networkAcls').virtualNetworkRules, createArray()))]", + "input": { + "id": "[format('{0}/subnets/{1}', parameters('vNetId'), if(contains(parameters('networkAcls'), 'virtualNetworkRules'), parameters('networkAcls').virtualNetworkRules, createArray())[copyIndex('virtualNetworkRules')].subnet)]" + } + }, + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ], + "maxNameLength": 24, + "uniquenameUntrim": "[uniqueString(format('Key Vault{0}', parameters('baseTime')))]", + "uniquename": "[if(greater(length(variables('uniquenameUntrim')), variables('maxNameLength')), substring(variables('uniquenameUntrim'), 0, variables('maxNameLength')), variables('uniquenameUntrim'))]", + "name_var": "[if(empty(parameters('name')), variables('uniquename'), parameters('name'))]", + "networkAcls_var": { + "bypass": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').bypass)]", + "defaultAction": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').defaultAction)]", + "virtualNetworkRules": "[if(empty(parameters('networkAcls')), null(), variables('virtualNetworkRules'))]", + "ipRules": "[if(empty(parameters('networkAcls')), null(), if(equals(length(parameters('networkAcls').ipRules), 0), createArray(), parameters('networkAcls').ipRules))]" + }, + "secretList": "[if(not(empty(parameters('secrets'))), parameters('secrets').secureList, createArray())]" + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2019-09-01", + "name": "[variables('name_var')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "enabledForDeployment": "[parameters('enableVaultForDeployment')]", + "enabledForTemplateDeployment": "[parameters('enableVaultForTemplateDeployment')]", + "enabledForDiskEncryption": "[parameters('enableVaultForDiskEncryption')]", + "enableSoftDelete": "[parameters('enableSoftDelete')]", + "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]", + "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]", + "createMode": "[parameters('createMode')]", + "enablePurgeProtection": "[if(not(parameters('enablePurgeProtection')), null(), parameters('enablePurgeProtection'))]", + "tenantId": "[subscription().tenantId]", + "accessPolicies": "[variables('formattedAccessPolicies')]", + "sku": { + "name": "[parameters('vaultSku')]", + "family": "A" + }, + "networkAcls": "[if(empty(parameters('networkAcls')), null(), variables('networkAcls_var'))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-{1}-lock', variables('name_var'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-diagnosticSettingName', variables('name_var'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "accessPolicies": { + "value": "[variables('formattedAccessPolicies')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "6661321759482511252" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "defaultValue": "add", + "metadata": { + "description": "Optional. The access policy deployment" + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2021-06-01-preview", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the access policies assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the access policies assignment" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_secrets", + "count": "[length(variables('secretList'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('secretList')[copyIndex()].name]" + }, + "value": { + "value": "[variables('secretList')[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesEnabled'), variables('secretList')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesExp'), variables('secretList')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesNbf'), variables('secretList')[copyIndex()].attributesNbf, -1)]" + }, + "contentType": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'contentType'), variables('secretList')[copyIndex()].contentType, '')]" + }, + "tags": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'tags'), variables('secretList')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'roleAssignments'), variables('secretList')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "12270664086129789391" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "secureString", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "value": "[parameters('value')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "secret_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4359461376172816756" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the secret." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the secret." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the secret was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_keys", + "count": "[length(parameters('keys'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('keys')[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesEnabled'), parameters('keys')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesExp'), parameters('keys')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesNbf'), parameters('keys')[copyIndex()].attributesNbf, -1)]" + }, + "curveName": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'curveName'), parameters('keys')[copyIndex()].curveName, 'P-256')]" + }, + "keyOps": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keyOps'), parameters('keys')[copyIndex()].keyOps, createArray())]" + }, + "keySize": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keySize'), parameters('keys')[copyIndex()].keySize, -1)]" + }, + "kty": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'kty'), parameters('keys')[copyIndex()].kty, 'EC')]" + }, + "tags": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'tags'), parameters('keys')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'roleAssignments'), parameters('keys')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10712670446155811230" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "curveName": { + "type": "string", + "defaultValue": "P-256", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "metadata": { + "description": "Optional. The elliptic curve name." + } + }, + "keyOps": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation" + } + }, + "keySize": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA." + } + }, + "kty": { + "type": "string", + "defaultValue": "EC", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "metadata": { + "description": "Optional. The type of the key." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "curveName": "[parameters('curveName')]", + "keyOps": "[parameters('keyOps')]", + "keySize": "[if(not(equals(parameters('keySize'), -1)), parameters('keySize'), null())]", + "kty": "[parameters('kty')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "key_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11678636666584394346" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the key." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the key." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7667998987627803701" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + }, + { + "condition": "[not(empty(variables('privateEndpoint_var').privateDnsZoneResourceIds))]", + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/default', variables('privateEndpoint_var').name)]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds)))]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9791358369810945169" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]", + "metadata": { + "description": "The resource ID of the key vault." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key vault was created in." + } + }, + "name": { + "type": "string", + "value": "[variables('name_var')]", + "metadata": { + "description": "The name of the key vault." + } + }, + "uri": { + "type": "string", + "value": "[reference(resourceId('Microsoft.KeyVault/vaults', variables('name_var'))).vaultUri]", + "metadata": { + "description": "The URI of the key vault." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Compute-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Shared-Services-KeyVault-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedServicesKvName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "enableRbacAuthorization": { + "value": false + }, + "softDeleteRetentionInDays": { + "value": 7 + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4895311282793848977" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "maxLength": 24, + "metadata": { + "description": "Optional. Name of the Key Vault. If no name is provided, then unique name will be created." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of access policies object" + } + }, + "secrets": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. All secrets to create" + } + }, + "keys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. All keys to create" + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute" + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment" + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "allowedValues": [ + true, + false + ], + "metadata": { + "description": "Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios." + } + }, + "enableSoftDelete": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "defaultValue": 90, + "metadata": { + "description": "Optional. softDelete data retention days. It accepts >=7 and <=90." + } + }, + "enableRbacAuthorization": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC." + } + }, + "createMode": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "vaultSku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault" + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "vNetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Virtual Network resource identifier, if networkAcls is passed, this value must be passed as well" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. " + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub" + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "AuditEvent" + ], + "allowedValues": [ + "AuditEvent" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(if(contains(parameters('networkAcls'), 'virtualNetworkRules'), parameters('networkAcls').virtualNetworkRules, createArray()))]", + "input": { + "id": "[format('{0}/subnets/{1}', parameters('vNetId'), if(contains(parameters('networkAcls'), 'virtualNetworkRules'), parameters('networkAcls').virtualNetworkRules, createArray())[copyIndex('virtualNetworkRules')].subnet)]" + } + }, + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ], + "maxNameLength": 24, + "uniquenameUntrim": "[uniqueString(format('Key Vault{0}', parameters('baseTime')))]", + "uniquename": "[if(greater(length(variables('uniquenameUntrim')), variables('maxNameLength')), substring(variables('uniquenameUntrim'), 0, variables('maxNameLength')), variables('uniquenameUntrim'))]", + "name_var": "[if(empty(parameters('name')), variables('uniquename'), parameters('name'))]", + "networkAcls_var": { + "bypass": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').bypass)]", + "defaultAction": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').defaultAction)]", + "virtualNetworkRules": "[if(empty(parameters('networkAcls')), null(), variables('virtualNetworkRules'))]", + "ipRules": "[if(empty(parameters('networkAcls')), null(), if(equals(length(parameters('networkAcls').ipRules), 0), createArray(), parameters('networkAcls').ipRules))]" + }, + "secretList": "[if(not(empty(parameters('secrets'))), parameters('secrets').secureList, createArray())]" + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2019-09-01", + "name": "[variables('name_var')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "enabledForDeployment": "[parameters('enableVaultForDeployment')]", + "enabledForTemplateDeployment": "[parameters('enableVaultForTemplateDeployment')]", + "enabledForDiskEncryption": "[parameters('enableVaultForDiskEncryption')]", + "enableSoftDelete": "[parameters('enableSoftDelete')]", + "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]", + "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]", + "createMode": "[parameters('createMode')]", + "enablePurgeProtection": "[if(not(parameters('enablePurgeProtection')), null(), parameters('enablePurgeProtection'))]", + "tenantId": "[subscription().tenantId]", + "accessPolicies": "[variables('formattedAccessPolicies')]", + "sku": { + "name": "[parameters('vaultSku')]", + "family": "A" + }, + "networkAcls": "[if(empty(parameters('networkAcls')), null(), variables('networkAcls_var'))]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-{1}-lock', variables('name_var'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', variables('name_var'))]", + "name": "[format('{0}-diagnosticSettingName', variables('name_var'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "accessPolicies": { + "value": "[variables('formattedAccessPolicies')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "6661321759482511252" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "defaultValue": "add", + "metadata": { + "description": "Optional. The access policy deployment" + } + }, + "accessPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(parameters('accessPolicies'))]", + "input": { + "applicationId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'applicationId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].applicationId, '')]", + "objectId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'objectId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].objectId, '')]", + "permissions": "[parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[if(contains(parameters('accessPolicies')[copyIndex('formattedAccessPolicies')], 'tenantId'), parameters('accessPolicies')[copyIndex('formattedAccessPolicies')].tenantId, tenant().tenantId)]" + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2021-06-01-preview", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the access policies assignment" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the access policies assignment" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_secrets", + "count": "[length(variables('secretList'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('secretList')[copyIndex()].name]" + }, + "value": { + "value": "[variables('secretList')[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesEnabled'), variables('secretList')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesExp'), variables('secretList')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'attributesNbf'), variables('secretList')[copyIndex()].attributesNbf, -1)]" + }, + "contentType": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'contentType'), variables('secretList')[copyIndex()].contentType, '')]" + }, + "tags": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'tags'), variables('secretList')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(variables('secretList')[copyIndex()], 'roleAssignments'), variables('secretList')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "12270664086129789391" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "secureString", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "value": "[parameters('value')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "secret_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4359461376172816756" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the secret." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the secret." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the secret was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_keys", + "count": "[length(parameters('keys'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('keys')[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[variables('name_var')]" + }, + "attributesEnabled": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesEnabled'), parameters('keys')[copyIndex()].attributesEnabled, true())]" + }, + "attributesExp": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesExp'), parameters('keys')[copyIndex()].attributesExp, -1)]" + }, + "attributesNbf": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'attributesNbf'), parameters('keys')[copyIndex()].attributesNbf, -1)]" + }, + "curveName": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'curveName'), parameters('keys')[copyIndex()].curveName, 'P-256')]" + }, + "keyOps": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keyOps'), parameters('keys')[copyIndex()].keyOps, createArray())]" + }, + "keySize": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'keySize'), parameters('keys')[copyIndex()].keySize, -1)]" + }, + "kty": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'kty'), parameters('keys')[copyIndex()].kty, 'EC')]" + }, + "tags": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'tags'), parameters('keys')[copyIndex()].tags, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('keys')[copyIndex()], 'roleAssignments'), parameters('keys')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10712670446155811230" + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the key vault" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "curveName": { + "type": "string", + "defaultValue": "P-256", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "metadata": { + "description": "Optional. The elliptic curve name." + } + }, + "keyOps": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation" + } + }, + "keySize": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA." + } + }, + "kty": { + "type": "string", + "defaultValue": "EC", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "metadata": { + "description": "Optional. The type of the key." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2019-09-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[if(not(equals(parameters('attributesExp'), -1)), parameters('attributesExp'), null())]", + "nbf": "[if(not(equals(parameters('attributesNbf'), -1)), parameters('attributesNbf'), null())]" + }, + "curveName": "[parameters('curveName')]", + "keyOps": "[parameters('keyOps')]", + "keySize": "[if(not(equals(parameters('keySize'), -1)), parameters('keySize'), null())]", + "kty": "[parameters('kty')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "key_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11678636666584394346" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[0], split(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), '/')[1])]", + "name": "[guid(format('{0}/{1}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the key." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the key." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7667998987627803701" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + }, + { + "condition": "[not(empty(variables('privateEndpoint_var').privateDnsZoneResourceIds))]", + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/default', variables('privateEndpoint_var').name)]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds)))]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[range(0, length(variables('privateEndpoint_var').privateDnsZoneResourceIds))[copyIndex('privateDnsZoneConfigs')]]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + }, + { + "copy": { + "name": "keyVault_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-KeyVault-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9791358369810945169" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Key Vault Administrator (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User (preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults', variables('name_var'))]", + "metadata": { + "description": "The resource ID of the key vault." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the key vault was created in." + } + }, + "name": { + "type": "string", + "value": "[variables('name_var')]", + "metadata": { + "description": "The name of the key vault." + } + }, + "uri": { + "type": "string", + "value": "[reference(resourceId('Microsoft.KeyVault/vaults', variables('name_var'))).vaultUri]", + "metadata": { + "description": "The URI of the key vault." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Fslogix-Storage-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdStorageObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdFslogixStorageName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "storageAccountSku": { + "value": "[parameters('fsLogixstorageSku')]" + }, + "allowBlobPublicAccess": { + "value": false + }, + "storageAccountKind": { + "value": "[if(or(equals(toLower(parameters('fsLogixstorageSku')), toLower('Premium_LRS')), equals(toLower(parameters('fsLogixstorageSku')), toLower('Premium_ZRS'))), 'FileStorage', 'StorageV2')]" + }, + "storageAccountAccessTier": { + "value": "Hot" + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Deny", + "virtualNetworkRules": [], + "ipRules": [] + } + }, + "fileServices": { + "value": { + "shares": [ + { + "name": "[variables('avdFslogixFileShareName')]", + "shareQuota": "[mul(parameters('avdFslogixFileShareQuotaSize'), 100)]" + } + ] + } + }, + "privateEndpoints": { + "value": [ + { + "subnetResourceId": "[if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time')))).outputs.resourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId'))]", + "service": "file" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "5501656653992230187" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Storage Account." + }, + "maxLength": 24 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "storageAccountKind": { + "type": "string", + "defaultValue": "StorageV2", + "metadata": { + "description": "Optional. Type of Storage Account to create." + }, + "allowedValues": [ + "Storage", + "StorageV2", + "BlobStorage", + "FileStorage", + "BlockBlobStorage" + ] + }, + "storageAccountSku": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage Account Sku Name." + }, + "allowedValues": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS", + "Premium_ZRS", + "Standard_GZRS", + "Standard_RAGZRS" + ] + }, + "storageAccountAccessTier": { + "type": "string", + "defaultValue": "Hot", + "metadata": { + "description": "Optional. Storage Account Access Tier." + }, + "allowedValues": [ + "Hot", + "Cool" + ] + }, + "azureFilesIdentityBasedAuthentication": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Provides the identity based authentication settings for Azure Files." + } + }, + "vNetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Virtual Network Identifier used to create a service endpoint." + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "managementPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Storage Account ManagementPolicies Rules." + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true." + } + }, + "blobServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Blob service and containers to deploy" + } + }, + "fileServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. File service and shares to deploy" + } + }, + "queueServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Queue service and queues to create." + } + }, + "tableServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Table service and tables to create." + } + }, + "allowBlobPublicAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "TLS1_2", + "metadata": { + "description": "Optional. Set the minimum TLS version on request to storage." + }, + "allowedValues": [ + "TLS1_0", + "TLS1_1", + "TLS1_2" + ] + }, + "enableHierarchicalNamespace": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If true, enables Hierarchical Namespace for the storage account" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "basetime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "supportsHttpsTrafficOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Allows https traffic only to storage service if sets to true." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(range(0, if(empty(parameters('networkAcls')), 0, length(parameters('networkAcls').virtualNetworkRules))))]", + "input": { + "id": "[format('{0}/subnets/{1}', parameters('vNetId'), parameters('networkAcls').virtualNetworkRules[range(0, if(empty(parameters('networkAcls')), 0, length(parameters('networkAcls').virtualNetworkRules)))[copyIndex('virtualNetworkRules')]].subnet)]" + } + } + ], + "networkAcls_var": { + "bypass": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').bypass)]", + "defaultAction": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').defaultAction)]", + "virtualNetworkRules": "[if(empty(parameters('networkAcls')), null(), variables('virtualNetworkRules'))]", + "ipRules": "[if(empty(parameters('networkAcls')), null(), if(equals(length(parameters('networkAcls').ipRules), 0), null(), parameters('networkAcls').ipRules))]" + }, + "azureFilesIdentityBasedAuthentication_var": "[parameters('azureFilesIdentityBasedAuthentication')]", + "maxNameLength": 24, + "uniqueStoragenameUntrim": "[format('{0}', uniqueString(format('Storage Account{0}', parameters('basetime'))))]", + "uniqueStoragename": "[if(greater(length(variables('uniqueStoragenameUntrim')), variables('maxNameLength')), substring(variables('uniqueStoragenameUntrim'), 0, variables('maxNameLength')), variables('uniqueStoragenameUntrim'))]", + "saBaseProperties": { + "encryption": { + "keySource": "Microsoft.Storage", + "services": { + "blob": "[if(or(or(or(equals(parameters('storageAccountKind'), 'BlockBlobStorage'), equals(parameters('storageAccountKind'), 'BlobStorage')), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage')), json('{\"enabled\": true}'), null())]", + "file": "[if(or(or(equals(parameters('storageAccountKind'), 'FileStorage'), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage')), json('{\"enabled\": true}'), null())]" + } + }, + "accessTier": "[if(equals(parameters('storageAccountKind'), 'Storage'), null(), parameters('storageAccountAccessTier'))]", + "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]", + "isHnsEnabled": "[if(not(parameters('enableHierarchicalNamespace')), null(), parameters('enableHierarchicalNamespace'))]", + "minimumTlsVersion": "[parameters('minimumTlsVersion')]", + "networkAcls": "[if(empty(parameters('networkAcls')), null(), variables('networkAcls_var'))]", + "allowBlobPublicAccess": "[parameters('allowBlobPublicAccess')]", + "requireInfrastructureEncryption": "[parameters('requireInfrastructureEncryption')]" + }, + "saOptIdBasedAuthProperties": { + "azureFilesIdentityBasedAuthentication": "[variables('azureFilesIdentityBasedAuthentication_var')]" + }, + "saProperties": "[if(empty(parameters('azureFilesIdentityBasedAuthentication')), variables('saBaseProperties'), union(variables('saBaseProperties'), variables('saOptIdBasedAuthProperties')))]", + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2021-06-01", + "name": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]", + "location": "[parameters('location')]", + "kind": "[parameters('storageAccountKind')]", + "sku": { + "name": "[parameters('storageAccountSku')]" + }, + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "properties": "[variables('saProperties')]" + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "name": "[format('{0}-diagnosticSettings', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "properties": { + "storageAccountId": "[if(empty(parameters('diagnosticStorageAccountId')), null(), parameters('diagnosticStorageAccountId'))]", + "workspaceId": "[if(empty(parameters('diagnosticWorkspaceId')), null(), parameters('diagnosticWorkspaceId'))]", + "eventHubAuthorizationRuleId": "[if(empty(parameters('diagnosticEventHubAuthorizationRuleId')), null(), parameters('diagnosticEventHubAuthorizationRuleId'))]", + "eventHubName": "[if(empty(parameters('diagnosticEventHubName')), null(), parameters('diagnosticEventHubName'))]", + "metrics": "[variables('diagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "name": "[format('{0}-{1}-lock', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "storageAccount_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10387762200517168414" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('privateEndpoints')))]", + "copy": { + "name": "storageAccount_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-PrivateEndpoints-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7899289128437460715" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/{1}', variables('privateEndpoint_var').name, 'default')]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(variables('privateEndpoint_var').privateDnsZoneResourceIds)]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('managementPolicyRules')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-ManagementPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "rules": { + "value": "[parameters('managementPolicyRules')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15085697909410876891" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the storage container to deploy" + } + }, + "rules": { + "type": "array", + "metadata": { + "description": "Required. The Storage Account ManagementPolicies Rules" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "condition": "[not(empty(parameters('rules')))]", + "type": "Microsoft.Storage/storageAccounts/managementPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "policy": { + "rules": "[parameters('rules')]" + } + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The resource ID of the deployed management policy" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed management policy" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed management policy" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('blobServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-BlobServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "containers": { + "value": "[if(contains(parameters('blobServices'), 'containers'), parameters('blobServices').containers, createArray())]" + }, + "automaticSnapshotPolicyEnabled": { + "value": "[if(contains(parameters('blobServices'), 'automaticSnapshotPolicyEnabled'), parameters('blobServices').automaticSnapshotPolicyEnabled, false())]" + }, + "deleteRetentionPolicy": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicy'), parameters('blobServices').deleteRetentionPolicy, true())]" + }, + "deleteRetentionPolicyDays": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicyDays'), parameters('blobServices').deleteRetentionPolicyDays, 7)]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogsRetentionInDays'), parameters('blobServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticStorageAccountId'), parameters('blobServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('blobServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubName'), parameters('blobServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'logsToEnable'), parameters('blobServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'metricsToEnable'), parameters('blobServices').metricsToEnable, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticWorkspaceId'), parameters('blobServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2898537581571618545" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the blob service" + } + }, + "deleteRetentionPolicy": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service." + } + }, + "deleteRetentionPolicyDays": { + "type": "int", + "defaultValue": 7, + "metadata": { + "description": "Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365." + } + }, + "automaticSnapshotPolicyEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Automatic Snapshot is enabled if set to true." + } + }, + "containers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Blob containers to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "deleteRetentionPolicy": { + "enabled": "[parameters('deleteRetentionPolicy')]", + "days": "[parameters('deleteRetentionPolicyDays')]" + }, + "automaticSnapshotPolicyEnabled": "[parameters('automaticSnapshotPolicyEnabled')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "blobServices_container", + "count": "[length(parameters('containers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Container-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('containers')[copyIndex()].name]" + }, + "publicAccess": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'publicAccess'), parameters('containers')[copyIndex()].publicAccess, 'None')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'roleAssignments'), parameters('containers')[copyIndex()].roleAssignments, createArray())]" + }, + "immutabilityPolicyProperties": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'immutabilityPolicyProperties'), parameters('containers')[copyIndex()].immutabilityPolicyProperties, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11320711469846624183" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage container to deploy" + } + }, + "immutabilityPolicyName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "publicAccess": { + "type": "string", + "defaultValue": "None", + "metadata": { + "description": "Optional. Specifies whether data in the container may be accessed publicly and the level of access." + }, + "allowedValues": [ + "Container", + "Blob", + "None" + ] + }, + "immutabilityPolicyProperties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Configure immutability policy." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "properties": { + "publicAccess": "[parameters('publicAccess')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('immutabilityPolicyProperties')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[parameters('immutabilityPolicyName')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('blobServicesName')]" + }, + "containerName": { + "value": "[parameters('name')]" + }, + "immutabilityPeriodSinceCreationInDays": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'immutabilityPeriodSinceCreationInDays'), parameters('immutabilityPolicyProperties').immutabilityPeriodSinceCreationInDays, 365)]" + }, + "allowProtectedAppendWrites": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'allowProtectedAppendWrites'), parameters('immutabilityPolicyProperties').allowProtectedAppendWrites, true())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17689091005602585327" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "containerName": { + "type": "string", + "metadata": { + "description": "Required. Name of the container to apply the policy to" + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "immutabilityPeriodSinceCreationInDays": { + "type": "int", + "defaultValue": 365, + "metadata": { + "description": "Optional. The immutability period for the blobs in the container since the policy creation, in days." + } + }, + "allowProtectedAppendWrites": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "properties": { + "immutabilityPeriodSinceCreationInDays": "[parameters('immutabilityPeriodSinceCreationInDays')]", + "allowProtectedAppendWrites": "[parameters('allowProtectedAppendWrites')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed immutability policy." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed immutability policy." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed immutability policy." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "container_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10442262648395245065" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}/containers/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed container" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed container" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed container" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed blob service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed blob service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the deployed blob service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('fileServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-FileServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogsRetentionInDays'), parameters('fileServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticStorageAccountId'), parameters('fileServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('fileServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubName'), parameters('fileServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'logsToEnable'), parameters('fileServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'metricsToEnable'), parameters('fileServices').metricsToEnable, createArray())]" + }, + "protocolSettings": { + "value": "[if(contains(parameters('fileServices'), 'protocolSettings'), parameters('fileServices').protocolSettings, createObject())]" + }, + "shareDeleteRetentionPolicy": { + "value": "[if(contains(parameters('fileServices'), 'shareDeleteRetentionPolicy'), parameters('fileServices').shareDeleteRetentionPolicy, createObject('enabled', true(), 'days', 7))]" + }, + "shares": { + "value": "[if(contains(parameters('fileServices'), 'shares'), parameters('fileServices').shares, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticWorkspaceId'), parameters('fileServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "5980876527120451803" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "protocolSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Protocol settings for file service" + } + }, + "shareDeleteRetentionPolicy": { + "type": "object", + "defaultValue": { + "enabled": true, + "days": 7 + }, + "metadata": { + "description": "Optional. The service properties for soft delete." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "shares": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. File shares to create." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "protocolSettings": "[parameters('protocolSettings')]", + "shareDeleteRetentionPolicy": "[parameters('shareDeleteRetentionPolicy')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "fileServices_shares", + "count": "[length(parameters('shares'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-File-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "fileServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('shares')[copyIndex()].name]" + }, + "sharedQuota": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'sharedQuota'), parameters('shares')[copyIndex()].sharedQuota, 5120)]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'roleAssignments'), parameters('shares')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17732962448495939013" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "fileServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the file share to create" + } + }, + "sharedQuota": { + "type": "int", + "defaultValue": 5120, + "metadata": { + "description": "Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/fileServices/shares", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "properties": { + "shareQuota": "[parameters('sharedQuota')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "fileShare_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2588830416148459608" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}/shares/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('queueServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-QueueServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogsRetentionInDays'), parameters('queueServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticStorageAccountId'), parameters('queueServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('queueServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubName'), parameters('queueServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'logsToEnable'), parameters('queueServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'metricsToEnable'), parameters('queueServices').metricsToEnable, createArray())]" + }, + "queues": { + "value": "[if(contains(parameters('queueServices'), 'queues'), parameters('queueServices').queues, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticWorkspaceId'), parameters('queueServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17351586310319401000" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "queues": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Queues to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/queueServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "queueServices_queues", + "count": "[length(parameters('queues'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Queue-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "queueServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('queues')[copyIndex()].name]" + }, + "metadata": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'metadata'), parameters('queues')[copyIndex()].metadata, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'roleAssignments'), parameters('queues')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9242208480564699240" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "queueServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage queue to deploy" + } + }, + "metadata": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Required. A name-value pair that represents queue metadata." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/queueServices/queues", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "queue_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[format('{0}', resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "16623058381927265088" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Dsms Role (deprecated)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b')]", + "Dsms Role (do not use)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f')]", + "GenevaWarmPathResourceContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}/queues/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed queue" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed queue" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed queue" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('tableServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-TableServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogsRetentionInDays'), parameters('tableServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticStorageAccountId'), parameters('tableServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('tableServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubName'), parameters('tableServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'logsToEnable'), parameters('tableServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'metricsToEnable'), parameters('tableServices').metricsToEnable, createArray())]" + }, + "tables": { + "value": "[if(contains(parameters('tableServices'), 'tables'), parameters('tableServices').tables, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticWorkspaceId'), parameters('tableServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3232028759446328437" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. tables to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/tableServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/tableServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "tableServices_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Table-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "tableServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15702770362989896381" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "tableServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/tableServices/tables", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]" + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices/tables', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed table service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed table service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed table service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "metadata": { + "description": "The resource ID of the deployed storage account" + } + }, + "name": { + "type": "string", + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]", + "metadata": { + "description": "The name of the deployed storage account" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed storage account" + } + }, + "primaryBlobEndpoint": { + "type": "string", + "value": "[if(and(not(empty(parameters('blobServices'))), contains(parameters('blobServices'), 'containers')), reference(format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2019-04-01').primaryEndpoints.blob, '')]", + "metadata": { + "description": "The primary blob endpoint reference if blob services are deployed." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2021-06-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2021-06-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Storage-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Shared-Services-Storage-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdShrdlSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdSharedResourcesRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdSharedSResourcesStorageName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "storageAccountSku": { + "value": "[if(parameters('avdUseAvailabilityZones'), 'Standard_ZRS', 'Standard_LRS')]" + }, + "storageAccountKind": { + "value": "StorageV2" + }, + "blobServices": { + "value": { + "containers": [ + { + "name": "[variables('avdSharedSResourcesAibContainerName')]", + "publicAccess": "None" + }, + { + "name": "[variables('avdSharedSResourcesScriptsContainerName')]", + "publicAccess": "None" + } + ] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "5501656653992230187" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Storage Account." + }, + "maxLength": 24 + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "storageAccountKind": { + "type": "string", + "defaultValue": "StorageV2", + "metadata": { + "description": "Optional. Type of Storage Account to create." + }, + "allowedValues": [ + "Storage", + "StorageV2", + "BlobStorage", + "FileStorage", + "BlockBlobStorage" + ] + }, + "storageAccountSku": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage Account Sku Name." + }, + "allowedValues": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS", + "Premium_ZRS", + "Standard_GZRS", + "Standard_RAGZRS" + ] + }, + "storageAccountAccessTier": { + "type": "string", + "defaultValue": "Hot", + "metadata": { + "description": "Optional. Storage Account Access Tier." + }, + "allowedValues": [ + "Hot", + "Cool" + ] + }, + "azureFilesIdentityBasedAuthentication": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Provides the identity based authentication settings for Azure Files." + } + }, + "vNetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Virtual Network Identifier used to create a service endpoint." + } + }, + "privateEndpoints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Configuration Details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible" + } + }, + "managementPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Storage Account ManagementPolicies Rules." + } + }, + "networkAcls": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny" + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. A boolean indicating whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest. For security reasons, it is recommended to set it to true." + } + }, + "blobServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Blob service and containers to deploy" + } + }, + "fileServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. File service and shares to deploy" + } + }, + "queueServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Queue service and queues to create." + } + }, + "tableServices": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Table service and tables to create." + } + }, + "allowBlobPublicAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether public access is enabled for all blobs or containers in the storage account. For security reasons, it is recommended to set it to false." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "TLS1_2", + "metadata": { + "description": "Optional. Set the minimum TLS version on request to storage." + }, + "allowedValues": [ + "TLS1_0", + "TLS1_1", + "TLS1_2" + ] + }, + "enableHierarchicalNamespace": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If true, enables Hierarchical Namespace for the storage account" + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "basetime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a SAS token to access the modules." + } + }, + "supportsHttpsTrafficOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Allows https traffic only to storage service if sets to true." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(range(0, if(empty(parameters('networkAcls')), 0, length(parameters('networkAcls').virtualNetworkRules))))]", + "input": { + "id": "[format('{0}/subnets/{1}', parameters('vNetId'), parameters('networkAcls').virtualNetworkRules[range(0, if(empty(parameters('networkAcls')), 0, length(parameters('networkAcls').virtualNetworkRules)))[copyIndex('virtualNetworkRules')]].subnet)]" + } + } + ], + "networkAcls_var": { + "bypass": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').bypass)]", + "defaultAction": "[if(empty(parameters('networkAcls')), null(), parameters('networkAcls').defaultAction)]", + "virtualNetworkRules": "[if(empty(parameters('networkAcls')), null(), variables('virtualNetworkRules'))]", + "ipRules": "[if(empty(parameters('networkAcls')), null(), if(equals(length(parameters('networkAcls').ipRules), 0), null(), parameters('networkAcls').ipRules))]" + }, + "azureFilesIdentityBasedAuthentication_var": "[parameters('azureFilesIdentityBasedAuthentication')]", + "maxNameLength": 24, + "uniqueStoragenameUntrim": "[format('{0}', uniqueString(format('Storage Account{0}', parameters('basetime'))))]", + "uniqueStoragename": "[if(greater(length(variables('uniqueStoragenameUntrim')), variables('maxNameLength')), substring(variables('uniqueStoragenameUntrim'), 0, variables('maxNameLength')), variables('uniqueStoragenameUntrim'))]", + "saBaseProperties": { + "encryption": { + "keySource": "Microsoft.Storage", + "services": { + "blob": "[if(or(or(or(equals(parameters('storageAccountKind'), 'BlockBlobStorage'), equals(parameters('storageAccountKind'), 'BlobStorage')), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage')), json('{\"enabled\": true}'), null())]", + "file": "[if(or(or(equals(parameters('storageAccountKind'), 'FileStorage'), equals(parameters('storageAccountKind'), 'StorageV2')), equals(parameters('storageAccountKind'), 'Storage')), json('{\"enabled\": true}'), null())]" + } + }, + "accessTier": "[if(equals(parameters('storageAccountKind'), 'Storage'), null(), parameters('storageAccountAccessTier'))]", + "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]", + "isHnsEnabled": "[if(not(parameters('enableHierarchicalNamespace')), null(), parameters('enableHierarchicalNamespace'))]", + "minimumTlsVersion": "[parameters('minimumTlsVersion')]", + "networkAcls": "[if(empty(parameters('networkAcls')), null(), variables('networkAcls_var'))]", + "allowBlobPublicAccess": "[parameters('allowBlobPublicAccess')]", + "requireInfrastructureEncryption": "[parameters('requireInfrastructureEncryption')]" + }, + "saOptIdBasedAuthProperties": { + "azureFilesIdentityBasedAuthentication": "[variables('azureFilesIdentityBasedAuthentication_var')]" + }, + "saProperties": "[if(empty(parameters('azureFilesIdentityBasedAuthentication')), variables('saBaseProperties'), union(variables('saBaseProperties'), variables('saOptIdBasedAuthProperties')))]", + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2021-06-01", + "name": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]", + "location": "[parameters('location')]", + "kind": "[parameters('storageAccountKind')]", + "sku": { + "name": "[parameters('storageAccountSku')]" + }, + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "properties": "[variables('saProperties')]" + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "name": "[format('{0}-diagnosticSettings', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "properties": { + "storageAccountId": "[if(empty(parameters('diagnosticStorageAccountId')), null(), parameters('diagnosticStorageAccountId'))]", + "workspaceId": "[if(empty(parameters('diagnosticWorkspaceId')), null(), parameters('diagnosticWorkspaceId'))]", + "eventHubAuthorizationRuleId": "[if(empty(parameters('diagnosticEventHubAuthorizationRuleId')), null(), parameters('diagnosticEventHubAuthorizationRuleId'))]", + "eventHubName": "[if(empty(parameters('diagnosticEventHubName')), null(), parameters('diagnosticEventHubName'))]", + "metrics": "[variables('diagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "name": "[format('{0}-{1}-lock', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "storageAccount_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10387762200517168414" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('privateEndpoints')))]", + "copy": { + "name": "storageAccount_privateEndpoints", + "count": "[length(parameters('privateEndpoints'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-PrivateEndpoints-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateEndpointResourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + }, + "privateEndpointVnetLocation": { + "value": "[if(empty(parameters('privateEndpoints')), 'dummy', reference(split(parameters('privateEndpoints')[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "privateEndpointObj": { + "value": "[parameters('privateEndpoints')[copyIndex()]]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "7899289128437460715" + } + }, + "parameters": { + "privateEndpointResourceId": { + "type": "string" + }, + "privateEndpointVnetLocation": { + "type": "string" + }, + "privateEndpointObj": { + "type": "object" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "privateEndpointResourceName": "[last(split(parameters('privateEndpointResourceId'), '/'))]", + "privateEndpoint_var": { + "name": "[if(contains(parameters('privateEndpointObj'), 'name'), if(empty(parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service), parameters('privateEndpointObj').name), format('{0}-{1}', variables('privateEndpointResourceName'), parameters('privateEndpointObj').service))]", + "subnetResourceId": "[parameters('privateEndpointObj').subnetResourceId]", + "service": [ + "[parameters('privateEndpointObj').service]" + ], + "privateDnsZoneResourceIds": "[if(contains(parameters('privateEndpointObj'), 'privateDnsZoneResourceIds'), if(empty(parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray(), parameters('privateEndpointObj').privateDnsZoneResourceIds), createArray())]", + "customDnsConfigs": "[if(contains(parameters('privateEndpointObj'), 'customDnsConfigs'), if(empty(parameters('privateEndpointObj').customDnsConfigs), null(), parameters('privateEndpointObj').customDnsConfigs), null())]" + } + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2021-02-01", + "name": "[format('{0}/{1}', variables('privateEndpoint_var').name, 'default')]", + "properties": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(variables('privateEndpoint_var').privateDnsZoneResourceIds)]", + "input": { + "name": "[last(split(variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[variables('privateEndpoint_var').privateDnsZoneResourceIds[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpoint_var').name)]" + ] + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2021-05-01", + "name": "[variables('privateEndpoint_var').name]", + "location": "[parameters('privateEndpointVnetLocation')]", + "tags": "[parameters('tags')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpoint_var').name]", + "properties": { + "privateLinkServiceId": "[parameters('privateEndpointResourceId')]", + "groupIds": "[variables('privateEndpoint_var').service]" + } + } + ], + "manualPrivateLinkServiceConnections": [], + "subnet": { + "id": "[variables('privateEndpoint_var').subnetResourceId]" + }, + "customDnsConfigs": "[variables('privateEndpoint_var').customDnsConfigs]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('managementPolicyRules')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-ManagementPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "rules": { + "value": "[parameters('managementPolicyRules')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15085697909410876891" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the storage container to deploy" + } + }, + "rules": { + "type": "array", + "metadata": { + "description": "Required. The Storage Account ManagementPolicies Rules" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "condition": "[not(empty(parameters('rules')))]", + "type": "Microsoft.Storage/storageAccounts/managementPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "policy": { + "rules": "[parameters('rules')]" + } + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The resource ID of the deployed management policy" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed management policy" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed management policy" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('blobServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-BlobServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "containers": { + "value": "[if(contains(parameters('blobServices'), 'containers'), parameters('blobServices').containers, createArray())]" + }, + "automaticSnapshotPolicyEnabled": { + "value": "[if(contains(parameters('blobServices'), 'automaticSnapshotPolicyEnabled'), parameters('blobServices').automaticSnapshotPolicyEnabled, false())]" + }, + "deleteRetentionPolicy": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicy'), parameters('blobServices').deleteRetentionPolicy, true())]" + }, + "deleteRetentionPolicyDays": { + "value": "[if(contains(parameters('blobServices'), 'deleteRetentionPolicyDays'), parameters('blobServices').deleteRetentionPolicyDays, 7)]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticLogsRetentionInDays'), parameters('blobServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticStorageAccountId'), parameters('blobServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('blobServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticEventHubName'), parameters('blobServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'logsToEnable'), parameters('blobServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('blobServices'), 'metricsToEnable'), parameters('blobServices').metricsToEnable, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('blobServices'), 'diagnosticWorkspaceId'), parameters('blobServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2898537581571618545" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the blob service" + } + }, + "deleteRetentionPolicy": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether DeleteRetentionPolicy is enabled for the Blob service." + } + }, + "deleteRetentionPolicyDays": { + "type": "int", + "defaultValue": 7, + "metadata": { + "description": "Optional. Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365." + } + }, + "automaticSnapshotPolicyEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Automatic Snapshot is enabled if set to true." + } + }, + "containers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Blob containers to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "deleteRetentionPolicy": { + "enabled": "[parameters('deleteRetentionPolicy')]", + "days": "[parameters('deleteRetentionPolicyDays')]" + }, + "automaticSnapshotPolicyEnabled": "[parameters('automaticSnapshotPolicyEnabled')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "blobServices_container", + "count": "[length(parameters('containers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Container-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('containers')[copyIndex()].name]" + }, + "publicAccess": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'publicAccess'), parameters('containers')[copyIndex()].publicAccess, 'None')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'roleAssignments'), parameters('containers')[copyIndex()].roleAssignments, createArray())]" + }, + "immutabilityPolicyProperties": { + "value": "[if(contains(parameters('containers')[copyIndex()], 'immutabilityPolicyProperties'), parameters('containers')[copyIndex()].immutabilityPolicyProperties, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11320711469846624183" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage container to deploy" + } + }, + "immutabilityPolicyName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "publicAccess": { + "type": "string", + "defaultValue": "None", + "metadata": { + "description": "Optional. Specifies whether data in the container may be accessed publicly and the level of access." + }, + "allowedValues": [ + "Container", + "Blob", + "None" + ] + }, + "immutabilityPolicyProperties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Configure immutability policy." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "properties": { + "publicAccess": "[parameters('publicAccess')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "condition": "[not(empty(parameters('immutabilityPolicyProperties')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[parameters('immutabilityPolicyName')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "blobServicesName": { + "value": "[parameters('blobServicesName')]" + }, + "containerName": { + "value": "[parameters('name')]" + }, + "immutabilityPeriodSinceCreationInDays": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'immutabilityPeriodSinceCreationInDays'), parameters('immutabilityPolicyProperties').immutabilityPeriodSinceCreationInDays, 365)]" + }, + "allowProtectedAppendWrites": { + "value": "[if(contains(parameters('immutabilityPolicyProperties'), 'allowProtectedAppendWrites'), parameters('immutabilityPolicyProperties').allowProtectedAppendWrites, true())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17689091005602585327" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "blobServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the blob service." + } + }, + "containerName": { + "type": "string", + "metadata": { + "description": "Required. Name of the container to apply the policy to" + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. Name of the immutable policy." + } + }, + "immutabilityPeriodSinceCreationInDays": { + "type": "int", + "defaultValue": 365, + "metadata": { + "description": "Optional. The immutability period for the blobs in the container since the policy creation, in days." + } + }, + "allowProtectedAppendWrites": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. This property can only be changed for unlocked time-based retention policies. When enabled, new blocks can be written to an append blob while maintaining immutability protection and compliance. Only new blocks can be added and any existing blocks cannot be modified or deleted. This property cannot be changed with ExtendImmutabilityPolicy API" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "properties": { + "immutabilityPeriodSinceCreationInDays": "[parameters('immutabilityPeriodSinceCreationInDays')]", + "allowProtectedAppendWrites": "[parameters('allowProtectedAppendWrites')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed immutability policy." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies', parameters('storageAccountName'), parameters('blobServicesName'), parameters('containerName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed immutability policy." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed immutability policy." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + }, + { + "copy": { + "name": "container_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "10442262648395245065" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/blobServices/{1}/containers/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed container" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices/containers', parameters('storageAccountName'), parameters('blobServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed container" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed container" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed blob service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed blob service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the deployed blob service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('fileServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-FileServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticLogsRetentionInDays'), parameters('fileServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticStorageAccountId'), parameters('fileServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('fileServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticEventHubName'), parameters('fileServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'logsToEnable'), parameters('fileServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('fileServices'), 'metricsToEnable'), parameters('fileServices').metricsToEnable, createArray())]" + }, + "protocolSettings": { + "value": "[if(contains(parameters('fileServices'), 'protocolSettings'), parameters('fileServices').protocolSettings, createObject())]" + }, + "shareDeleteRetentionPolicy": { + "value": "[if(contains(parameters('fileServices'), 'shareDeleteRetentionPolicy'), parameters('fileServices').shareDeleteRetentionPolicy, createObject('enabled', true(), 'days', 7))]" + }, + "shares": { + "value": "[if(contains(parameters('fileServices'), 'shares'), parameters('fileServices').shares, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('fileServices'), 'diagnosticWorkspaceId'), parameters('fileServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "5980876527120451803" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "protocolSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Protocol settings for file service" + } + }, + "shareDeleteRetentionPolicy": { + "type": "object", + "defaultValue": { + "enabled": true, + "days": 7 + }, + "metadata": { + "description": "Optional. The service properties for soft delete." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "shares": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. File shares to create." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": { + "protocolSettings": "[parameters('protocolSettings')]", + "shareDeleteRetentionPolicy": "[parameters('shareDeleteRetentionPolicy')]" + } + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "fileServices_shares", + "count": "[length(parameters('shares'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-File-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "fileServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('shares')[copyIndex()].name]" + }, + "sharedQuota": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'sharedQuota'), parameters('shares')[copyIndex()].sharedQuota, 5120)]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('shares')[copyIndex()], 'roleAssignments'), parameters('shares')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17732962448495939013" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "fileServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the file service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the file share to create" + } + }, + "sharedQuota": { + "type": "int", + "defaultValue": 5120, + "metadata": { + "description": "Optional. The maximum size of the share, in gigabytes. Must be greater than 0, and less than or equal to 5TB (5120). For Large File Shares, the maximum size is 102400." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/fileServices/shares", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "properties": { + "shareQuota": "[parameters('sharedQuota')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "fileShare_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2588830416148459608" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Blob Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "Storage Blob Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "Storage Blob Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')]", + "Storage Blob Delegator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a')]", + "Storage File Data SMB Share Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb')]", + "Storage File Data SMB Share Elevated Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7264617-510b-434b-a828-9731dc254ea7')]", + "Storage File Data SMB Share Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'aba4ae5f-2193-4029-9191-0cb91df5e314')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "Storage Table Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]", + "Storage Table Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76199698-9eea-4c19-bc75-cec21354c6b6')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/fileServices/{1}/shares/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices/shares', parameters('storageAccountName'), parameters('fileServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/fileServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('queueServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-QueueServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticLogsRetentionInDays'), parameters('queueServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticStorageAccountId'), parameters('queueServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('queueServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticEventHubName'), parameters('queueServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'logsToEnable'), parameters('queueServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('queueServices'), 'metricsToEnable'), parameters('queueServices').metricsToEnable, createArray())]" + }, + "queues": { + "value": "[if(contains(parameters('queueServices'), 'queues'), parameters('queueServices').queues, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('queueServices'), 'diagnosticWorkspaceId'), parameters('queueServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17351586310319401000" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "queues": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Queues to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/queueServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "queueServices_queues", + "count": "[length(parameters('queues'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Queue-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "queueServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('queues')[copyIndex()].name]" + }, + "metadata": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'metadata'), parameters('queues')[copyIndex()].metadata, createObject())]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('queues')[copyIndex()], 'roleAssignments'), parameters('queues')[copyIndex()].roleAssignments, createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9242208480564699240" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "queueServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the queue service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the storage queue to deploy" + } + }, + "metadata": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Required. A name-value pair that represents queue metadata." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/queueServices/queues", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "properties": { + "metadata": "[parameters('metadata')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "queue_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[format('{0}', resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "16623058381927265088" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Dsms Role (deprecated)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b91f4c0b-46e3-47bb-a242-eecfe23b3b5b')]", + "Dsms Role (do not use)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7aff565e-6c55-448d-83db-ccf482c6da2f')]", + "GenevaWarmPathResourceContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Logic App Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '87a39d53-fc1b-424a-814c-f7e04687dc9e')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reader and Data Access": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c12c1c16-33a1-487b-954d-41c89c60f349')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Site Recovery Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6670b86e-a3f7-4917-ac9b-5d6ab1be4567')]", + "Site Recovery Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '494ae006-db33-4328-bf46-533a6560a3ca')]", + "Storage Account Backup Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1')]", + "Storage Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", + "Storage Account Key Operator Service Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "Storage Queue Data Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')]", + "Storage Queue Data Message Processor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8a0f0c08-91a1-4084-bc3d-661d67233fed')]", + "Storage Queue Data Message Sender": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a')]", + "Storage Queue Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '19e7f393-937e-4f77-808e-94535e297925')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/queueServices/{1}/queues/{2}', split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[0], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[1], split(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), '/')[2])]", + "name": "[guid(format('{0}/{1}/{2}', split(parameters('resourceId'), '/')[8], split(parameters('resourceId'), '/')[10], split(parameters('resourceId'), '/')[12]), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed queue" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices/queues', parameters('storageAccountName'), parameters('queueServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed queue" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed queue" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + }, + { + "condition": "[not(empty(parameters('tableServices')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Storage-TableServices', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticLogsRetentionInDays'), parameters('tableServices').diagnosticLogsRetentionInDays, 365)]" + }, + "diagnosticStorageAccountId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticStorageAccountId'), parameters('tableServices').diagnosticStorageAccountId, '')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubAuthorizationRuleId'), parameters('tableServices').diagnosticEventHubAuthorizationRuleId, '')]" + }, + "diagnosticEventHubName": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticEventHubName'), parameters('tableServices').diagnosticEventHubName, '')]" + }, + "logsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'logsToEnable'), parameters('tableServices').logsToEnable, createArray())]" + }, + "metricsToEnable": { + "value": "[if(contains(parameters('tableServices'), 'metricsToEnable'), parameters('tableServices').metricsToEnable, createArray())]" + }, + "tables": { + "value": "[if(contains(parameters('tableServices'), 'tables'), parameters('tableServices').tables, createArray())]" + }, + "diagnosticWorkspaceId": { + "value": "[if(contains(parameters('tableServices'), 'diagnosticWorkspaceId'), parameters('tableServices').diagnosticWorkspaceId, '')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "3232028759446328437" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. tables to create." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "logsToEnable": { + "type": "array", + "defaultValue": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "allowedValues": [ + "StorageRead", + "StorageWrite", + "StorageDelete" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "Transaction" + ], + "allowedValues": [ + "Transaction" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/tableServices", + "apiVersion": "2021-04-01", + "name": "[format('{0}/{1}', parameters('storageAccountName'), parameters('name'))]", + "properties": {} + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Storage/storageAccounts/{0}/tableServices/{1}', parameters('storageAccountName'), parameters('name'))]", + "name": "[format('{0}-diagnosticSettings', parameters('name'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "tableServices_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Table-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "storageAccountName": { + "value": "[parameters('storageAccountName')]" + }, + "tableServicesName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15702770362989896381" + } + }, + "parameters": { + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Storage Account." + }, + "maxLength": 24 + }, + "tableServicesName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the table service" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts/tableServices/tables", + "apiVersion": "2021-06-01", + "name": "[format('{0}/{1}/{2}', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]" + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed file share service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices/tables', parameters('storageAccountName'), parameters('tableServicesName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed file share service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed file share service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the deployed table service" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts/tableServices', parameters('storageAccountName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the deployed table service" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed table service" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]" + ] + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename')))]", + "metadata": { + "description": "The resource ID of the deployed storage account" + } + }, + "name": { + "type": "string", + "value": "[if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))]", + "metadata": { + "description": "The name of the deployed storage account" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group of the deployed storage account" + } + }, + "primaryBlobEndpoint": { + "type": "string", + "value": "[if(and(not(empty(parameters('blobServices'))), contains(parameters('blobServices'), 'containers')), reference(format('Microsoft.Storage/storageAccounts/{0}', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2019-04-01').primaryEndpoints.blob, '')]", + "metadata": { + "description": "The primary blob endpoint reference if blob services are deployed." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2021-06-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Storage/storageAccounts', if(not(empty(parameters('name'))), parameters('name'), variables('uniqueStoragename'))), '2021-06-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdShrdlSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Shared-Resources-{0}', parameters('time')))]" + ] + }, + { + "condition": "[and(not(parameters('avdUseAvailabilityZones')), parameters('avdDeploySessionHosts'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Availability-Set-{0}', parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('avdAvailabilitySetName')]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "availabilitySetFaultDomain": { + "value": 3 + }, + "availabilitySetUpdateDomain": { + "value": 5 + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4979342573601033887" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the availability set that is being created." + } + }, + "availabilitySetFaultDomain": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "Optional. The number of fault domains to use." + } + }, + "availabilitySetUpdateDomain": { + "type": "int", + "defaultValue": 5, + "metadata": { + "description": "Optional. The number of update domains to use." + } + }, + "availabilitySetSku": { + "type": "string", + "defaultValue": "Aligned", + "metadata": { + "description": "Optional. Sku of the availability set. Use 'Aligned' for virtual machines with managed disks and 'Classic' for virtual machines with unmanaged disks." + } + }, + "proximityPlacementGroupId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a proximity placement group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Resource location." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the availability set resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/availabilitySets", + "apiVersion": "2021-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "platformFaultDomainCount": "[parameters('availabilitySetFaultDomain')]", + "platformUpdateDomainCount": "[parameters('availabilitySetUpdateDomain')]", + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupId'))), createObject('id', parameters('proximityPlacementGroupId')), null())]" + }, + "sku": { + "name": "[parameters('availabilitySetSku')]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/availabilitySets/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "availabilitySet_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-AvSet-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "1165502185304219973" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Cluster Create": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Azure Service Deploy Release Management Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21d96096-b162-414a-8302-d8354f9d91b2')]", + "CAL-Custom-Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7b266cd7-0bba-4ae2-8423-90ede5e1e898')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "masterreader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a48d7796-14b4-4889-afef-fbb65a93e5a2')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/availabilitySets/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the availability set" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/availabilitySets', parameters('name'))]", + "metadata": { + "description": "The resource ID of the availability set" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the availability set was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Compute-{0}', parameters('time')))]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "copy": { + "name": "avdSessionHosts", + "count": "[length(range(0, parameters('avdDeploySessionHostsCount')))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('AVD-Session-Host-{0}-{1}', range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}-{1}', variables('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()])]" + }, + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "systemAssignedIdentity": { + "value": true + }, + "availabilityZone": { + "value": "[if(parameters('avdUseAvailabilityZones'), take(skip(variables('allAvailabilityZones'), mod(range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], length(variables('allAvailabilityZones')))), 1), createArray())]" + }, + "encryptionAtHost": { + "value": "[parameters('encryptionAtHost')]" + }, + "availabilitySetName": { + "value": "[if(not(parameters('avdUseAvailabilityZones')), if(parameters('avdDeploySessionHosts'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Availability-Set-{0}', parameters('time')))).outputs.name.value, ''), '')]" + }, + "osType": { + "value": "Windows" + }, + "licenseType": { + "value": "Windows_Client" + }, + "vmSize": { + "value": "[parameters('avdSessionHostsSize')]" + }, + "imageReference": { + "value": "[if(parameters('useSharedImage'), json(format('{{''id'': ''{0}''}}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))).outputs.resourceId.value)), variables('marketPlaceGalleryWindows')[parameters('avdOsImage')])]" + }, + "osDisk": { + "value": { + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": 128, + "managedDisk": { + "storageAccountType": "[parameters('avdSessionHostDiskType')]" + } + } + }, + "adminUsername": { + "value": "[parameters('avdVmLocalUserName')]" + }, + "adminPassword": { + "value": "[parameters('avdVmLocalUserPassword')]" + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "deleteOption": "Delete", + "asgId": "[if(parameters('createAvdVnet'), format('{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-ASG-{0}', parameters('time')))).outputs.resourceId.value), null())]", + "enableAcceleratedNetworking": false, + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "[if(parameters('createAvdVnet'), format('{0}/subnets/{1}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time')))).outputs.resourceId.value, variables('avdVnetworkSubnetName')), parameters('existingVnetSubnetResourceId'))]" + } + ] + } + ] + }, + "allowExtensionOperations": { + "value": true + }, + "extensionDomainJoinPassword": { + "value": "[parameters('avdDomainJoinUserPassword')]" + }, + "extensionDomainJoinConfig": { + "value": { + "enabled": true, + "settings": { + "name": "[parameters('avdIdentityDomainName')]", + "ouPath": "[if(not(empty(parameters('avdOuPath'))), parameters('avdOuPath'), null())]", + "user": "[parameters('avdDomainJoinUserName')]", + "restart": "true", + "options": "3" + } + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": true, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "isEnabled": "true", + "day": "7", + "time": "120", + "scanType": "Quick" + }, + "Exclusions": { + "Extensions": "*.vhd;*.vhdx", + "Paths": "\"%ProgramFiles%\\FSLogix\\Apps\\frxdrv.sys;%ProgramFiles%\\FSLogix\\Apps\\frxccd.sys;%ProgramFiles%\\FSLogix\\Apps\\frxdrvvt.sys;%TEMP%\\*.VHD;%TEMP%\\*.VHDX;%Windir%\\TEMP\\*.VHD;%Windir%\\TEMP\\*.VHDX;\\\\server\\share\\*\\*.VHD;\\\\server\\share\\*\\*.VHDX", + "Processes": "%ProgramFiles%\\FSLogix\\Apps\\frxccd.exe;%ProgramFiles%\\FSLogix\\Apps\\frxccds.exe;%ProgramFiles%\\FSLogix\\Apps\\frxsvc.exe" + } + } + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "2892701365879213703" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[take(toLower(uniqueString(resourceGroup().name)), 10)]", + "metadata": { + "description": "Optional. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name." + } + }, + "vmComputerNamesTransformation": { + "type": "string", + "defaultValue": "none", + "metadata": { + "description": "Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'." + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_D2s_v3", + "metadata": { + "description": "Optional. Specifies the size for the VMs" + } + }, + "encryptionAtHost": { + "type": "bool", + "metadata": { + "description": "Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "securityType": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings." + } + }, + "secureBootEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "vTpmEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings." + } + }, + "imageReference": { + "type": "object", + "metadata": { + "description": "Required. OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image." + } + }, + "plan": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use." + } + }, + "osDisk": { + "type": "object", + "metadata": { + "description": "Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "dataDisks": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs." + } + }, + "ultraSSDEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled." + } + }, + "adminUsername": { + "type": "secureString", + "metadata": { + "description": "Required. Administrator username" + } + }, + "adminPassword": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed" + } + }, + "customData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format." + } + }, + "certificatesToBeInstalled": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies set of certificates that should be installed onto the virtual machine." + } + }, + "vmPriority": { + "type": "string", + "defaultValue": "Regular", + "allowedValues": [ + "Regular", + "Low", + "Spot" + ], + "metadata": { + "description": "Optional. Specifies the priority for the virtual machine." + } + }, + "enableEvictionPolicy": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy." + } + }, + "maxPriceForLowPriorityVm": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars." + } + }, + "dedicatedHostId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies resource ID about the dedicated host that the virtual machine resides in." + } + }, + "licenseType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Windows_Client", + "Windows_Server", + "" + ], + "metadata": { + "description": "Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system." + } + }, + "publicKeys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The list of SSH public keys used to authenticate with linux based VMs" + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "bootDiagnosticStorageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided." + } + }, + "bootDiagnosticStorageAccountUri": { + "type": "string", + "defaultValue": "[format('.blob.{0}/', environment().suffixes.storage)]", + "metadata": { + "description": "Optional. Storage account boot diagnostic base URI." + } + }, + "proximityPlacementGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource name of a proximity placement group." + } + }, + "availabilitySetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set." + } + }, + "availabilityZone": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. If the array is null then value would be set to 0 - no availability zones to be used. Must pass the zone leverage either pickZones function or pass down the array with zone number" + } + }, + "nicConfigurations": { + "type": "array", + "metadata": { + "description": "Required. Configures NICs and PIPs." + } + }, + "pipLogsToEnable": { + "type": "array", + "defaultValue": [ + "DDoSProtectionNotifications", + "DDoSMitigationFlowLogs", + "DDoSMitigationReports" + ], + "allowedValues": [ + "DDoSProtectionNotifications", + "DDoSMitigationFlowLogs", + "DDoSMitigationReports" + ], + "metadata": { + "description": "Optional. The name of logs that will be streamed." + } + }, + "pipMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "nicMetricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], + "allowedValues": [ + "AllMetrics" + ], + "metadata": { + "description": "Optional. The name of metrics that will be streamed." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Recovery service vault name to add VMs to backup." + } + }, + "backupVaultResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "DefaultPolicy", + "metadata": { + "description": "Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault." + } + }, + "enableServerSideEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key." + } + }, + "allowExtensionOperations": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine." + } + }, + "extensionDomainJoinPassword": { + "type": "secureString", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter" + } + }, + "extensionDomainJoinConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Domain Join] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionAntiMalwareConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Anti Malware] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionMonitoringAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "monitoringWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true." + } + }, + "extensionDependencyAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Dependency Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionNetworkWatcherAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionDiskEncryptionConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Disk Encryption] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionDSCConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "extensionCustomScriptConfig": { + "type": "object", + "defaultValue": { + "enabled": false, + "fileData": [] + }, + "metadata": { + "description": "Optional. The configuration for the [Custom Script] extension. Must at least contain the [\"enabled\": true] property to be executed" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "maxValue": 365, + "minValue": 0, + "metadata": { + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." + } + }, + "diagnosticStorageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account." + } + }, + "diagnosticWorkspaceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace." + } + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "diagnosticEventHubName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category." + } + }, + "lock": { + "type": "string", + "defaultValue": "NotSpecified", + "metadata": { + "description": "Optional. Specify the type of lock." + }, + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ] + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, 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'" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The chosen OS type" + } + }, + "disablePasswordAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether password authentication should be disabled." + } + }, + "provisionVMAgent": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later." + } + }, + "enableAutomaticUpdates": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones." + } + }, + "additionalUnattendContent": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object" + } + }, + "winRM": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object." + } + }, + "configurationProfileAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Any VM configuration profile assignments" + } + } + }, + "variables": { + "copy": [ + { + "name": "publicKeysFormatted", + "count": "[length(parameters('publicKeys'))]", + "input": { + "path": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].path]", + "keyData": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].keyData]" + } + } + ], + "vmComputerNameTransformed": "[if(equals(parameters('vmComputerNamesTransformation'), 'uppercase'), toUpper(parameters('name')), if(equals(parameters('vmComputerNamesTransformation'), 'lowercase'), toLower(parameters('name')), parameters('name')))]", + "linuxConfiguration": { + "disablePasswordAuthentication": "[parameters('disablePasswordAuthentication')]", + "ssh": { + "publicKeys": "[variables('publicKeysFormatted')]" + }, + "provisionVMAgent": "[parameters('provisionVMAgent')]" + }, + "windowsConfiguration": { + "provisionVMAgent": "[parameters('provisionVMAgent')]", + "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "timeZone": "[if(empty(parameters('timeZone')), null(), parameters('timeZone'))]", + "additionalUnattendContent": "[if(empty(parameters('additionalUnattendContent')), null(), parameters('additionalUnattendContent'))]", + "winRM": "[if(not(empty(parameters('winRM'))), createObject('listeners', parameters('winRM')), null())]" + }, + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + }, + "identityType": "[if(parameters('systemAssignedIdentity'), if(not(empty(parameters('userAssignedIdentities'))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "identity": "[if(not(equals(variables('identityType'), 'None')), createObject('type', variables('identityType'), 'userAssignedIdentities', if(not(empty(parameters('userAssignedIdentities'))), parameters('userAssignedIdentities'), null())), null())]" + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2021-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "zones": "[if(equals(parameters('availabilityZone'), ''), null(), parameters('availabilityZone'))]", + "plan": "[if(not(empty(parameters('plan'))), parameters('plan'), null())]", + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "securityProfile": "[if(parameters('encryptionAtHost'), createObject('encryptionAtHost', parameters('encryptionAtHost'), 'securityType', parameters('securityType'), 'uefiSettings', if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())), createObject('securityType', parameters('securityType'), 'uefiSettings', if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())))]", + "storageProfile": { + "copy": [ + { + "name": "dataDisks", + "count": "[length(parameters('dataDisks'))]", + "input": { + "lun": "[copyIndex('dataDisks')]", + "name": "[format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0'))]", + "diskSizeGB": "[parameters('dataDisks')[copyIndex('dataDisks')].diskSizeGB]", + "createOption": "[parameters('dataDisks')[copyIndex('dataDisks')].createOption]", + "deleteOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'deleteOption'), parameters('dataDisks')[copyIndex('dataDisks')].deleteOption, 'Delete')]", + "caching": "[parameters('dataDisks')[copyIndex('dataDisks')].caching]", + "managedDisk": { + "storageAccountType": "[parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.storageAccountType]", + "diskEncryptionSet": { + "id": "[if(parameters('enableServerSideEncryption'), parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.diskEncryptionSet.id, null())]" + } + } + } + } + ], + "imageReference": "[parameters('imageReference')]", + "osDisk": { + "name": "[format('{0}-disk-os-01', parameters('name'))]", + "createOption": "[parameters('osDisk').createOption]", + "deleteOption": "[if(contains(parameters('osDisk'), 'deleteOption'), parameters('osDisk').deleteOption, 'Delete')]", + "diskSizeGB": "[parameters('osDisk').diskSizeGB]", + "managedDisk": { + "storageAccountType": "[parameters('osDisk').managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('osDisk').managedDisk, 'diskEncryptionSet'), parameters('osDisk').managedDisk.diskEncryptionSet, null())]" + } + } + }, + "additionalCapabilities": { + "ultraSSDEnabled": "[parameters('ultraSSDEnabled')]" + }, + "osProfile": { + "computerName": "[variables('vmComputerNameTransformed')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]", + "customData": "[if(not(empty(parameters('customData'))), base64(parameters('customData')), null())]", + "windowsConfiguration": "[if(equals(parameters('osType'), 'Windows'), variables('windowsConfiguration'), null())]", + "linuxConfiguration": "[if(equals(parameters('osType'), 'Linux'), variables('linuxConfiguration'), null())]", + "secrets": "[parameters('certificatesToBeInstalled')]", + "allowExtensionOperations": "[parameters('allowExtensionOperations')]" + }, + "networkProfile": { + "copy": [ + { + "name": "networkInterfaces", + "count": "[length(parameters('nicConfigurations'))]", + "input": { + "properties": { + "deleteOption": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaces')], 'deleteOption'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].deleteOption, 'Delete')]", + "primary": "[if(equals(copyIndex('networkInterfaces'), 0), true(), false())]" + }, + "id": "[resourceId('Microsoft.Network/networkInterfaces', format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].nicSuffix))]" + } + } + ] + }, + "diagnosticsProfile": { + "bootDiagnostics": { + "enabled": "[not(empty(parameters('bootDiagnosticStorageAccountName')))]", + "storageUri": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), format('https://{0}{1}', parameters('bootDiagnosticStorageAccountName'), parameters('bootDiagnosticStorageAccountUri')), null())]" + } + }, + "availabilitySet": "[if(not(empty(parameters('availabilitySetName'))), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Compute/availabilitySets', parameters('availabilitySetName')))), null())]", + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupName'))), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Compute/proximityPlacementGroups', parameters('proximityPlacementGroupName')))), null())]", + "priority": "[parameters('vmPriority')]", + "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", + "billingProfile": "[if(and(not(empty(parameters('vmPriority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), json(format('{{\"maxPrice\":\"{0}\"}}', parameters('maxPriceForLowPriorityVm'))), null())]", + "host": "[if(not(empty(parameters('dedicatedHostId'))), json(format('{{\"id\":\"{0}\"}}', parameters('dedicatedHostId'))), null())]", + "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]" + }, + "dependsOn": [ + "virtualMachine_nic" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", + "name": "[format('{0}-{1}-lock', parameters('name'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + }, + { + "copy": { + "name": "virtualMachine_nic", + "count": "[length(parameters('nicConfigurations'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Nic-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "networkInterfaceName": { + "value": "[format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex()].nicSuffix)]" + }, + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "enableIPForwarding": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableIPForwarding'), if(not(empty(parameters('nicConfigurations')[copyIndex()].enableIPForwarding)), parameters('nicConfigurations')[copyIndex()].enableIPForwarding, false()), false())]" + }, + "enableAcceleratedNetworking": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableAcceleratedNetworking'), parameters('nicConfigurations')[copyIndex()].enableAcceleratedNetworking, true())]" + }, + "dnsServers": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'dnsServers'), if(not(empty(parameters('nicConfigurations')[copyIndex()].dnsServers)), parameters('nicConfigurations')[copyIndex()].dnsServers, createArray()), createArray())]" + }, + "networkSecurityGroupId": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'nsgId'), if(not(empty(parameters('nicConfigurations')[copyIndex()].nsgId)), parameters('nicConfigurations')[copyIndex()].nsgId, ''), '')]" + }, + "applicationSecurityGroupId": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'asgId'), if(not(empty(parameters('nicConfigurations')[copyIndex()].asgId)), parameters('nicConfigurations')[copyIndex()].asgId, ''), '')]" + }, + "ipConfigurationArray": { + "value": "[parameters('nicConfigurations')[copyIndex()].ipConfigurations]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "diagnosticStorageAccountId": { + "value": "[parameters('diagnosticStorageAccountId')]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[parameters('diagnosticLogsRetentionInDays')]" + }, + "diagnosticWorkspaceId": { + "value": "[parameters('diagnosticWorkspaceId')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[parameters('diagnosticEventHubAuthorizationRuleId')]" + }, + "diagnosticEventHubName": { + "value": "[parameters('diagnosticEventHubName')]" + }, + "metricsToEnable": { + "value": "[parameters('nicMetricsToEnable')]" + }, + "pipMetricsToEnable": { + "value": "[parameters('pipMetricsToEnable')]" + }, + "pipLogsToEnable": { + "value": "[parameters('pipLogsToEnable')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'roleAssignments'), if(not(empty(parameters('nicConfigurations')[copyIndex()].roleAssignments)), parameters('nicConfigurations')[copyIndex()].roleAssignments, createArray()), createArray())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "5784369176328296930" + } + }, + "parameters": { + "networkInterfaceName": { + "type": "string" + }, + "virtualMachineName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "tags": { + "type": "object" + }, + "enableIPForwarding": { + "type": "bool", + "defaultValue": false + }, + "enableAcceleratedNetworking": { + "type": "bool", + "defaultValue": false + }, + "dnsServers": { + "type": "array", + "defaultValue": [] + }, + "networkSecurityGroupId": { + "type": "string", + "defaultValue": "" + }, + "applicationSecurityGroupId": { + "type": "string", + "defaultValue": "" + }, + "ipConfigurationArray": { + "type": "array" + }, + "lock": { + "type": "string" + }, + "diagnosticStorageAccountId": { + "type": "string" + }, + "diagnosticLogsRetentionInDays": { + "type": "int" + }, + "diagnosticWorkspaceId": { + "type": "string" + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string" + }, + "diagnosticEventHubName": { + "type": "string" + }, + "pipMetricsToEnable": { + "type": "array" + }, + "pipLogsToEnable": { + "type": "array" + }, + "metricsToEnable": { + "type": "array" + }, + "roleAssignments": { + "type": "array" + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2021-03-01", + "name": "[parameters('networkInterfaceName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "ipConfigurations", + "count": "[length(parameters('ipConfigurationArray'))]", + "input": { + "name": "[if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].name)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].name, null())]", + "properties": { + "primary": "[if(equals(copyIndex('ipConfigurations'), 0), true(), false())]", + "applicationSecurityGroups": "[if(not(empty(parameters('applicationSecurityGroupId'))), createArray(createObject('id', parameters('applicationSecurityGroupId'))), null())]", + "privateIPAllocationMethod": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].privateIPAllocationMethod)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].privateIPAllocationMethod, null()), null())]", + "privateIPAddress": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'vmIPAddress'), if(not(empty(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].vmIPAddress)), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].vmIPAddress, null()), null())]", + "publicIPAddress": "[if(contains(parameters('ipConfigurationArray')[copyIndex('ipConfigurations')], 'pipconfiguration'), json(format('{{\"id\":\"{0}\"}}', resourceId('Microsoft.Network/publicIPAddresses', format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].pipconfiguration.publicIpNameSuffix)))), null())]", + "subnet": { + "id": "[parameters('ipConfigurationArray')[copyIndex('ipConfigurations')].subnetId]" + } + } + } + } + ], + "enableIPForwarding": "[parameters('enableIPForwarding')]", + "enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]", + "dnsSettings": "[if(not(empty(parameters('dnsServers'))), createObject('dnsServers', parameters('dnsServers')), null())]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupId'))), createObject('id', parameters('networkSecurityGroupId')), null())]" + }, + "dependsOn": [ + "networkInterface_publicIPConfigurations" + ] + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('networkInterfaceName'))]", + "name": "[format('{0}-{1}-lock', parameters('networkInterfaceName'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('networkInterfaceName'))]", + "name": "[format('{0}-diagnosticSettings', parameters('networkInterfaceName'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + }, + { + "condition": "[contains(parameters('ipConfigurationArray')[copyIndex()], 'pipconfiguration')]", + "copy": { + "name": "networkInterface_publicIPConfigurations", + "count": "[length(parameters('ipConfigurationArray'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-PIP-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "publicIPAddressName": { + "value": "[format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIpNameSuffix)]" + }, + "publicIPPrefixId": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'publicIPPrefixId'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPPrefixId)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPPrefixId, ''), '')]" + }, + "publicIPAllocationMethod": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'publicIPAllocationMethod'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPAllocationMethod)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.publicIPAllocationMethod, 'Static'), 'Static')]" + }, + "skuName": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'skuName'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuName)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuName, 'Standard'), 'Standard')]" + }, + "skuTier": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'skuTier'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuTier)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.skuTier, 'Regional'), 'Regional')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "diagnosticStorageAccountId": { + "value": "[parameters('diagnosticStorageAccountId')]" + }, + "diagnosticLogsRetentionInDays": { + "value": "[parameters('diagnosticLogsRetentionInDays')]" + }, + "diagnosticWorkspaceId": { + "value": "[parameters('diagnosticWorkspaceId')]" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "[parameters('diagnosticEventHubAuthorizationRuleId')]" + }, + "diagnosticEventHubName": { + "value": "[parameters('diagnosticEventHubName')]" + }, + "metricsToEnable": { + "value": "[parameters('pipMetricsToEnable')]" + }, + "logsToEnable": { + "value": "[parameters('pipLogsToEnable')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "roleAssignments": { + "value": "[if(contains(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration, 'roleAssignments'), if(not(empty(parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.roleAssignments)), parameters('ipConfigurationArray')[copyIndex()].pipconfiguration.roleAssignments, createArray()), createArray())]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "14835111508600582620" + } + }, + "parameters": { + "publicIPAddressName": { + "type": "string" + }, + "publicIPPrefixId": { + "type": "string" + }, + "publicIPAllocationMethod": { + "type": "string" + }, + "skuName": { + "type": "string" + }, + "skuTier": { + "type": "string" + }, + "location": { + "type": "string" + }, + "diagnosticStorageAccountId": { + "type": "string" + }, + "diagnosticLogsRetentionInDays": { + "type": "int" + }, + "diagnosticWorkspaceId": { + "type": "string" + }, + "diagnosticEventHubAuthorizationRuleId": { + "type": "string" + }, + "diagnosticEventHubName": { + "type": "string" + }, + "metricsToEnable": { + "type": "array" + }, + "logsToEnable": { + "type": "array" + }, + "lock": { + "type": "string" + }, + "roleAssignments": { + "type": "array" + }, + "tags": { + "type": "object" + } + }, + "variables": { + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2021-05-01", + "name": "[parameters('publicIPAddressName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "properties": { + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIPPrefixId'))), createObject('id', parameters('publicIPPrefixId')), null())]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('publicIPAddressName'))]", + "name": "[format('{0}-{1}-lock', parameters('publicIPAddressName'), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('publicIPAddressName'))]", + "name": "[format('{0}-diagnosticSettings', parameters('publicIPAddressName'))]", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + }, + { + "copy": { + "name": "publicIpAddress_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "14627436867473350253" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the public IP address was deployed." + } + }, + "name": { + "type": "string", + "value": "[parameters('publicIPAddressName')]", + "metadata": { + "description": "The name of the public IP address." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]", + "metadata": { + "description": "The resource ID of the public IP address." + } + } + } + } + } + }, + { + "copy": { + "name": "networkInterface_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-Rbac-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "11371198124967576666" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]" + ] + } + ] + } + } + }, + { + "copy": { + "name": "vm_configurationProfileAssignment", + "count": "[length(parameters('configurationProfileAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-ConfigurationProfileAssignment-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "configurationProfile": { + "value": "[parameters('configurationProfileAssignments')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "1221055330468311616" + } + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the configuration profile assignment" + } + }, + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the VM to be associated" + } + }, + "configurationProfile": { + "type": "string", + "allowedValues": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest" + ], + "metadata": { + "description": "Required. The configuration profile of automanage" + } + } + }, + "resources": [ + { + "type": "Microsoft.Automanage/configurationProfileAssignments", + "apiVersion": "2021-04-30-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('virtualMachineName'))]", + "name": "[parameters('name')]", + "properties": { + "configurationProfile": "[parameters('configurationProfile')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "value": "[extensionResourceId(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName')), 'Microsoft.Automanage/configurationProfileAssignments', parameters('name'))]", + "metadata": { + "description": "The resource ID of the configuration profile assignment" + } + }, + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the configuration profile assignment" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The resource group the configuration profile assignment was deployed into" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDomainJoinConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DomainJoin" + }, + "publisher": { + "value": "Microsoft.Compute" + }, + "type": { + "value": "JsonADDomainExtension" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'typeHandlerVersion'), parameters('extensionDomainJoinConfig').typeHandlerVersion, '1.3')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDomainJoinConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDomainJoinConfig'), 'enableAutomaticUpgrade'), parameters('extensionDomainJoinConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[parameters('extensionDomainJoinConfig').settings]" + }, + "protectedSettings": { + "value": { + "Password": "[parameters('extensionDomainJoinPassword')]" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionAntiMalwareConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftAntiMalware" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "IaaSAntimalware" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'typeHandlerVersion'), parameters('extensionAntiMalwareConfig').typeHandlerVersion, '1.3')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'autoUpgradeMinorVersion'), parameters('extensionAntiMalwareConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionAntiMalwareConfig'), 'enableAutomaticUpgrade'), parameters('extensionAntiMalwareConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[parameters('extensionAntiMalwareConfig').settings]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionMonitoringAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftMonitoringAgent" + }, + "publisher": { + "value": "Microsoft.EnterpriseCloud.Monitoring" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'MicrosoftMonitoringAgent', 'OmsAgentForLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'typeHandlerVersion'), parameters('extensionMonitoringAgentConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '1.0', '1.7'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionMonitoringAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionMonitoringAgentConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": { + "workspaceId": "[if(not(empty(parameters('monitoringWorkspaceId'))), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('monitoringWorkspaceId'), '/')[2], split(parameters('monitoringWorkspaceId'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(parameters('monitoringWorkspaceId'), '/'))), '2021-06-01').customerId, '')]" + } + }, + "protectedSettings": { + "value": { + "workspaceKey": "[if(not(empty(parameters('monitoringWorkspaceId'))), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('monitoringWorkspaceId'), '/')[2], split(parameters('monitoringWorkspaceId'), '/')[4]), 'Microsoft.OperationalInsights/workspaces', last(split(parameters('monitoringWorkspaceId'), '/'))), '2021-06-01').primarySharedKey, '')]" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDependencyAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DependencyAgent" + }, + "publisher": { + "value": "Microsoft.Azure.Monitoring.DependencyAgent" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'DependencyAgentWindows', 'DependencyAgentLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'typeHandlerVersion'), parameters('extensionDependencyAgentConfig').typeHandlerVersion, '9.5')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDependencyAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDependencyAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionDependencyAgentConfig').enableAutomaticUpgrade, true())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionNetworkWatcherAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "NetworkWatcherAgent" + }, + "publisher": { + "value": "Microsoft.Azure.NetworkWatcher" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'NetworkWatcherAgentWindows', 'NetworkWatcherAgentLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'typeHandlerVersion'), parameters('extensionNetworkWatcherAgentConfig').typeHandlerVersion, '1.4')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'autoUpgradeMinorVersion'), parameters('extensionNetworkWatcherAgentConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'enableAutomaticUpgrade'), parameters('extensionNetworkWatcherAgentConfig').enableAutomaticUpgrade, false())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionDSCConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DesiredStateConfiguration" + }, + "publisher": { + "value": "Microsoft.Powershell" + }, + "type": { + "value": "DSC" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'typeHandlerVersion'), parameters('extensionDSCConfig').typeHandlerVersion, '2.73')]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDSCConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'enableAutomaticUpgrade'), parameters('extensionDSCConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'settings'), parameters('extensionDSCConfig').settings, createObject())]" + }, + "protectedSettings": { + "value": "[if(contains(parameters('extensionDSCConfig'), 'protectedSettings'), parameters('extensionDSCConfig').protectedSettings, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + }, + { + "condition": "[parameters('extensionCustomScriptConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "CustomScriptExtension" + }, + "publisher": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'Microsoft.Compute', 'Microsoft.Azure.Extensions')]" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'CustomScriptExtension', 'CustomScript')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'typeHandlerVersion'), parameters('extensionCustomScriptConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '1.10', '2.1'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'autoUpgradeMinorVersion'), parameters('extensionCustomScriptConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'enableAutomaticUpgrade'), parameters('extensionCustomScriptConfig').enableAutomaticUpgrade, false())]" + }, + "settings": { + "value": { + "copy": [ + { + "name": "fileUris", + "count": "[length(parameters('extensionCustomScriptConfig').fileData)]", + "input": "[if(contains(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')], 'storageAccountId'), format('{0}?{1}', parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri, listAccountSas(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].storageAccountId, '2019-04-01', variables('accountSasProperties')).accountSasToken), parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri)]" + } + ] + } + }, + "protectedSettings": { + "value": "[if(contains(parameters('extensionCustomScriptConfig'), 'protectedSettings'), parameters('extensionCustomScriptConfig').protectedSettings, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "condition": "[parameters('extensionDiskEncryptionConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-DiskEncryption', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DiskEncryption" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "[if(equals(parameters('osType'), 'Windows'), 'AzureDiskEncryption', 'AzureDiskEncryptionForLinux')]" + }, + "typeHandlerVersion": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'typeHandlerVersion'), parameters('extensionDiskEncryptionConfig').typeHandlerVersion, if(equals(parameters('osType'), 'Windows'), '2.2', '1.1'))]" + }, + "autoUpgradeMinorVersion": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'autoUpgradeMinorVersion'), parameters('extensionDiskEncryptionConfig').autoUpgradeMinorVersion, true())]" + }, + "enableAutomaticUpgrade": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'enableAutomaticUpgrade'), parameters('extensionDiskEncryptionConfig').enableAutomaticUpgrade, false())]" + }, + "forceUpdateTag": { + "value": "[if(contains(parameters('extensionDiskEncryptionConfig'), 'forceUpdateTag'), parameters('extensionDiskEncryptionConfig').forceUpdateTag, '1.0')]" + }, + "settings": { + "value": "[parameters('extensionDiskEncryptionConfig').settings]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "9399373706173233716" + } + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine that extension is provisioned for" + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to" + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher" + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"" + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler" + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed" + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings" + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings" + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false" + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available" + } + }, + "cuaId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered" + } + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + } + }, + { + "condition": "[not(empty(parameters('cuaId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('pid-{0}', parameters('cuaId'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": {}, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "4174488789265615178" + } + }, + "resources": [] + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the extension" + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]", + "metadata": { + "description": "The resource ID of the extension" + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "condition": "[not(empty(parameters('backupVaultName')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Backup', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[parameters('backupVaultResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "backupResourceName": { + "value": "[format('{0}/Azure/iaasvmcontainer;iaasvmcontainerv2;{1};{2}/vm;iaasvmcontainerv2;{3};{4}', parameters('backupVaultName'), resourceGroup().name, parameters('name'), resourceGroup().name, parameters('name'))]" + }, + "protectedItemType": { + "value": "Microsoft.Compute/virtualMachines" + }, + "backupPolicyId": { + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('backupVaultName'), parameters('backupPolicyName'))]" + }, + "sourceResourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "17143783980097543843" + } + }, + "parameters": { + "backupResourceName": { + "type": "string" + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ] + }, + "backupPolicyId": { + "type": "string" + }, + "sourceResourceId": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2021-06-01", + "name": "[parameters('backupResourceName')]", + "location": "[resourceGroup().location]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('backupPolicyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-MicrosoftMonitoringAgent', uniqueString(deployment().name, parameters('location'))))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location'))))]" + ] + }, + { + "copy": { + "name": "virtualMachine_rbac", + "count": "[length(parameters('roleAssignments'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('{0}-VM-Rbac-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" + }, + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15787947253388245820" + } + }, + "parameters": { + "principalIds": { + "type": "array" + }, + "roleDefinitionIdOrName": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Avere Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f8fab4f-1852-4a58-a46a-8eaf358af14a')]", + "Avere Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Microsoft OneAsset Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fd1bb084-1503-4bd2-99c0-630220046786')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Metrics Publisher": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Reservation Purchaser": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f7b75c60-3036-4b75-91c3-6b41c27c1689')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2021-04-01-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(last(split(parameters('resourceId'), '/')), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + ] + } + ], + "outputs": { + "name": { + "type": "string", + "value": "[parameters('name')]", + "metadata": { + "description": "The name of the VM." + } + }, + "resourceId": { + "type": "string", + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]", + "metadata": { + "description": "The resource ID of the VM." + } + }, + "resourceGroupName": { + "type": "string", + "value": "[resourceGroup().name]", + "metadata": { + "description": "The name of the resource group the VM was created in." + } + }, + "systemAssignedPrincipalId": { + "type": "string", + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), '2021-07-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), '2021-07-01', 'full').identity.principalId, '')]", + "metadata": { + "description": "The principal ID of the system assigned identity." + } + } + } + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-ASG-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdComputeObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Availability-Set-{0}', parameters('time')))]", + "[subscriptionResourceId(variables('avdWrklSubscriptionId'), 'Microsoft.Resources/deployments', format('AVD-RG-Compute-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('Deploy-AVD-Image-Template-Definition-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdNetworkObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-vNet-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-Workload-KeyVault-{0}', parameters('time')))]", + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdShrdlSubscriptionId')), format('{0}', variables('avdSharedResourcesRgName'))), 'Microsoft.Resources/deployments', format('AVD-Build-Image-Template-{0}-Check-Build', parameters('avdOsImage')))]" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "copy": { + "name": "addAvdHostsToHostPool", + "count": "[length(range(0, parameters('avdDeploySessionHostsCount')))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Add-AVD-Session-Host-{0}-to-HostPool-{1}', range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "hostPoolToken": { + "value": "[format('{0}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))).outputs.hostPoolRestrationInfo.value.token)]" + }, + "name": { + "value": "[format('{0}-{1}', variables('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()])]" + }, + "hostPoolName": { + "value": "[variables('avdHostPoolName')]" + }, + "avdAgentPackageLocation": { + "value": "[variables('avdAgentPackageLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15866332551626423320" + } + }, + "parameters": { + "name": { + "type": "string" + }, + "location": { + "type": "string" + }, + "avdAgentPackageLocation": { + "type": "string" + }, + "hostPoolName": { + "type": "string" + }, + "systemData": { + "type": "object", + "defaultValue": {} + }, + "hostPoolToken": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/Microsoft.PowerShell.DSC', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.PowerShell", + "type": "DSC", + "typeHandlerVersion": "2.73", + "autoUpgradeMinorVersion": true, + "settings": { + "modulesUrl": "[parameters('avdAgentPackageLocation')]", + "configurationFunction": "Configuration.ps1\\AddSessionHost", + "properties": { + "hostPoolName": "[parameters('hostPoolName')]", + "registrationInfoToken": "[parameters('hostPoolToken')]", + "aadJoin": false, + "sessionHostConfigurationLastUpdateTime": "[if(contains(parameters('systemData'), 'hostpoolUpdate'), parameters('systemData').sessionHostConfigurationVersion, '')]" + } + } + } + } + ] + } + }, + "dependsOn": [ + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', format('{0}', variables('avdWrklSubscriptionId')), format('{0}', variables('avdServiceObjectsRgName'))), 'Microsoft.Resources/deployments', format('AVD-HostPool-{0}', parameters('time')))]", + "avdSessionHosts" + ] + }, + { + "condition": "[parameters('avdDeploySessionHosts')]", + "copy": { + "name": "configureFsLogixForAvdHosts", + "count": "[length(range(0, parameters('avdDeploySessionHostsCount')))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-10-01", + "name": "[format('Configure-FsLogix-for-{0}-{1}-{2}', variables('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()], parameters('time'))]", + "subscriptionId": "[format('{0}', variables('avdWrklSubscriptionId'))]", + "resourceGroup": "[format('{0}', variables('avdComputeObjectsRgName'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('avdSessionHostLocation')]" + }, + "name": { + "value": "[format('{0}-{1}', variables('avdSessionHostNamePrefix'), range(0, parameters('avdDeploySessionHostsCount'))[copyIndex()])]" + }, + "file": { + "value": "[variables('fsLogixScript')]" + }, + "FsLogixScriptArguments": { + "value": "[variables('FsLogixScriptArguments')]" + }, + "baseScriptUri": { + "value": "[variables('fslogixScriptUri')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.4.1272.37030", + "templateHash": "15058212372752875435" + } + }, + "parameters": { + "name": { + "type": "string" + }, + "location": { + "type": "string" + }, + "baseScriptUri": { + "type": "string" + }, + "file": { + "type": "string" + }, + "FsLogixScriptArguments": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2021-07-01", + "name": "[format('{0}/configurefslogix', parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "publisher": "Microsoft.Compute", + "type": "CustomScriptExtension", + "typeHandlerVersion": "1.10", + "autoUpgradeMinorVersion": true, + "settings": {}, + "protectedSettings": { + "fileUris": "[array(parameters('baseScriptUri'))]", + "commandToExecute": "[format('powershell -ExecutionPolicy Unrestricted -File {0} {1}', parameters('file'), parameters('FsLogixScriptArguments'))]" + } + } + } + ] + } + }, + "dependsOn": [ + "avdSessionHosts" + ] + } + ] +} \ No newline at end of file diff --git a/workload/bicep/avd-modules/avd-hostpool-app-groups.bicep b/workload/bicep/avd-modules/avd-hostpool-app-groups.bicep new file mode 100644 index 000000000..32afa85ff --- /dev/null +++ b/workload/bicep/avd-modules/avd-hostpool-app-groups.bicep @@ -0,0 +1,120 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Required. Location where to deploy AVD management plane') +param avdManagementPlaneLocation string + +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWorkloadSubsId string + +@description('AVD Resource Group Name for the service objects') +param avdServiceObjectsRgName string + +@description('Optional. AVD Application Group Name for the applications.') +param avdApplicationGroupNameRapp string + +@description('AVD Application group for the session hosts. Desktop type.') +param avdApplicationGroupNameDesktop string + +@description('Optional. AVD deploy remote app application group') +param avdDeployRappGroup bool + +@description('AVD Host Pool Name') +param avdHostPoolName string + +@description('Optional. AVD host pool Custom RDP properties') +param avdHostPoolRdpProperties string + +@allowed([ + 'Personal' + 'Pooled' +]) +@description('Optional. AVD host pool type (Default: Pooled)') +param avdHostPoolType string + +@allowed([ + 'Automatic' + 'Direct' +]) +@description('Optional. AVD host pool type (Default: Automatic)') +param avdPersonalAssignType string + +@allowed([ + 'BreadthFirst' + 'DepthFirst' +]) +@description('Required. AVD host pool load balacing type (Default: BreadthFirst)') +param avdHostPoolLoadBalancerType string + +@description('Optional. AVD host pool maximum number of user sessions per session host') +param avhHostPoolMaxSessions int + +@description('Optional. AVD host pool start VM on Connect') +param avdStartVmOnConnect bool + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Variable declaration // +// =========== // +var desktopApplicaitonGroups = [ + { + name: avdApplicationGroupNameDesktop + location: avdManagementPlaneLocation + applicationGroupType: 'Desktop' + } +] + +var applicationApplicationGroups = [ + { + name: avdApplicationGroupNameRapp + location: avdManagementPlaneLocation + applicationGroupType: 'RemoteApp' + } +] + +var finalApplicationGroups = avdDeployRappGroup ? concat(desktopApplicaitonGroups,applicationApplicationGroups): desktopApplicaitonGroups + +// =========== // +// Deployments // +// =========== // + +// Hostpool. +module avdHostPool '../../../carml/1.2.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep' = { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdServiceObjectsRgName}') + name: 'AVD-HostPool-${time}' + params: { + name: avdHostPoolName + location: avdManagementPlaneLocation + hostpoolType: avdHostPoolType + startVMOnConnect: avdStartVmOnConnect + customRdpProperty: avdHostPoolRdpProperties + loadBalancerType: avdHostPoolLoadBalancerType + maxSessionLimit: avhHostPoolMaxSessions + personalDesktopAssignmentType: avdPersonalAssignType + } +} + +// Application groups. +module avdApplicationGroups '../../../carml/1.2.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep' = [for applicationGroup in finalApplicationGroups: { +scope: resourceGroup('${avdWorkloadSubsId}', '${avdServiceObjectsRgName}') +name: 'Deploy-AppGroup-${applicationGroup.name}-${time}' +params: { + name: applicationGroup.name + location: applicationGroup.location + applicationGroupType: applicationGroup.applicationGroupType + hostpoolName: avdHostPool.outputs.name +} +dependsOn: [ + avdHostPool +] +}] + +// =========== // +// Outputs // +// =========== // +output avdAppGroupsArray array = [for (resourceId,i) in finalApplicationGroups : avdApplicationGroups[i].outputs.resourceId] +output hostPooltoken string = avdHostPool.outputs.hostPoolRestrationInfo.token diff --git a/workload/bicep/avd-modules/avd-identity.bicep b/workload/bicep/avd-modules/avd-identity.bicep new file mode 100644 index 000000000..980cae987 --- /dev/null +++ b/workload/bicep/avd-modules/avd-identity.bicep @@ -0,0 +1,115 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Required. Location where to deploy AVD management plane') +param avdManagementPlaneLocation string + +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWorkloadSubsId string + +@description('AVD Resource Group Name for the service objects') +param avdServiceObjectsRgName string + +@description('Resource Group name for the session hosts') +param avdComputeObjectsRgName string + +@description('Resource Group Name for Azure Files') +param avdStorageObjectsRgName string + +@description('Azure Virtual Desktop enterprise application object ID') +param avdEnterpriseAppObjectId string + +@description('Create custom Start VM on connect role') +param createStartVmOnConnectCustomRole bool + +@description('Deploy new session hosts') +param avdDeploySessionHosts bool + +@description('FSlogix Managed Identity name') +param fslogixManagedIdentityName string + +@description('GUID for built role Reader') +param readerRoleId string + +@description('GUID for built in role ID of Storage Account Contributor') +param storageAccountContributorRoleId string + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Deployments // +// =========== // + +// FSLogix managed identity. +module fslogixManagedIdentity '../../../carml/1.2.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = if (avdDeploySessionHosts) { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdServiceObjectsRgName}') + name: 'fslogix-Managed-Identity-${time}' + params: { + name: fslogixManagedIdentityName + location: avdManagementPlaneLocation + } +} + +// RBAC Roles. +module startVMonConnectRole '../../../carml/1.2.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep' = if (createStartVmOnConnectCustomRole) { + scope: subscription(avdWorkloadSubsId) + name: 'Start-VM-on-Connect-Role-${time}' + params: { + subscriptionId: avdWorkloadSubsId + description: 'Start VM on connect AVD' + roleName: 'StartVMonConnect-AVD' + location: avdManagementPlaneLocation + actions: [ + 'Microsoft.Compute/virtualMachines/start/action' + 'Microsoft.Compute/virtualMachines/*/read' + ] + assignableScopes: [ + '/subscriptions/${avdWorkloadSubsId}' + ] + } +} + +// RBAC role Assignments. +module startVMonConnectRoleAssign '../../../carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = if (createStartVmOnConnectCustomRole) { + name: 'Start-VM-OnConnect-RoleAssign-${time}' + scope: resourceGroup('${avdWorkloadSubsId}', '${avdComputeObjectsRgName}') + params: { + roleDefinitionIdOrName: createStartVmOnConnectCustomRole ? startVMonConnectRole.outputs.resourceId : '' + principalId: avdEnterpriseAppObjectId + } + dependsOn: [ + startVMonConnectRole + ] +} + +module fslogixConnectRoleAssign '../../../carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = if (avdDeploySessionHosts) { + name: 'fslogix-UserAIdentity-RoleAssign-${time}' + scope: resourceGroup('${avdWorkloadSubsId}', '${avdStorageObjectsRgName}') + params: { + roleDefinitionIdOrName: '/subscriptions/${avdWorkloadSubsId}/providers/Microsoft.Authorization/roleDefinitions/${storageAccountContributorRoleId}' + principalId: fslogixManagedIdentity.outputs.principalId + } + dependsOn: [ + fslogixManagedIdentity + ] +} + +module fslogixConnectReaderRoleAssign '../../../carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = if (avdDeploySessionHosts) { + name: 'fslogix-UserAIdentity-ReaderRoleAssign-${time}' + scope: resourceGroup('${avdWorkloadSubsId}', '${avdStorageObjectsRgName}') + params: { + roleDefinitionIdOrName: '/subscriptions/${avdWorkloadSubsId}/providers/Microsoft.Authorization/roleDefinitions/${readerRoleId}' + principalId: fslogixManagedIdentity.outputs.principalId + } + dependsOn: [ + fslogixManagedIdentity + ] +} + +// =========== // +// Outputs // +// =========== // +output fslogixManagedIdentityResourceId string = fslogixManagedIdentity.outputs.resourceId diff --git a/workload/bicep/avd-modules/avd-networking.bicep b/workload/bicep/avd-modules/avd-networking.bicep new file mode 100644 index 000000000..9aa2160b5 --- /dev/null +++ b/workload/bicep/avd-modules/avd-networking.bicep @@ -0,0 +1,191 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWorkloadSubsId string + +@description('Resource Group Name for the AVD session hosts') +param avdComputeObjectsRgName string + +// Optional parameters for the AVD session hosts virtual network. +@description('Create new virtual network') +param createAvdVnet bool + +@description('Optional. If new virtual network required for the AVD machines. Resource Group name for the virtual network.') +param avdNetworkObjectsRgName string + +@description('Optional. Name of the virtual network if required to be created') +param avdVnetworkName string + +@description('Network Security Group Name') +param avdNetworksecurityGroupName string + +@description('Optional. Created if hte new VNet for AVD is created. Application Security Group (ASG) for the session hosts') +param avdApplicationsecurityGroupName string + +@description('Optional. Created if the new VNet for AVD is created. Route Table name.') +param avdRouteTableName string + +@description('Does the hub contains a virtual network gateway') +param vNetworkGatewayOnHub bool + +@description('Existing hub virtual network for perring') +param existingHubVnetResourceId string + +@description('VNet peering name for AVD VNEt to vHub. ') +param avdVnetworkPeeringName string + +@description('AVD virtual network address prefixes') +param avdVnetworkAddressPrefixes string + +@description('AVD subnet Name') +param avdVnetworkSubnetName string + +@description('AVD virtual network subnet address prefix') +param avdVnetworkSubnetAddressPrefix string + +@description('custom DNS servers IPs') +param customDnsIps string + +@description('Required. Location where to deploy compute services') +param avdSessionHostLocation string = deployment().location + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Deployments // +// =========== // + +// Resource group. +module avdNetworkObjectsRg '../../../carml/1.2.0/Microsoft.Resources/resourceGroups/deploy.bicep' = if (createAvdVnet) { + scope: subscription(avdWorkloadSubsId) + name: 'AVD-RG-Network-${time}' + params: { + name: avdNetworkObjectsRgName + location: avdSessionHostLocation + } +} + +// Network security group. +module avdNetworksecurityGroup '../../../carml/1.2.0/Microsoft.Network/networkSecurityGroups/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdNetworkObjectsRgName}') + name: 'AVD-NSG-${time}' + params: { + name: avdNetworksecurityGroupName + location: avdSessionHostLocation + } + dependsOn: [ + avdNetworkObjectsRg + ] +} + +// Application security group. +module avdApplicationSecurityGroup '../../../carml/1.2.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdComputeObjectsRgName}') + name: 'AVD-ASG-${time}' + params: { + name: avdApplicationsecurityGroupName + location: avdSessionHostLocation + } + dependsOn: [] +} + +// Route table. +module avdRouteTable '../../../carml/1.2.0/Microsoft.Network/routeTables/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdNetworkObjectsRgName}') + name: 'AVD-UDR-${time}' + params: { + name: avdRouteTableName + location: avdSessionHostLocation + } + dependsOn: [ + avdNetworkObjectsRg + ] +} + +// Virtual network. +module avdVirtualNetwork '../../../carml/1.2.0/Microsoft.Network/virtualNetworks/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdNetworkObjectsRgName}') + name: 'AVD-vNet-${time}' + params: { + name: avdVnetworkName + location: avdSessionHostLocation + addressPrefixes: array(avdVnetworkAddressPrefixes) + dnsServers: !empty(customDnsIps) ? array(customDnsIps) : [] + virtualNetworkPeerings: [ + { + remoteVirtualNetworkId: existingHubVnetResourceId + name: avdVnetworkPeeringName + allowForwardedTraffic: true + allowGatewayTransit: false + allowVirtualNetworkAccess: true + doNotVerifyRemoteGateways: true + useRemoteGateways: vNetworkGatewayOnHub ? true : false + remotePeeringEnabled: true + remotePeeringName: avdVnetworkPeeringName + remotePeeringAllowForwardedTraffic: true + remotePeeringAllowGatewayTransit: vNetworkGatewayOnHub ? true : false + remotePeeringAllowVirtualNetworkAccess: true + remotePeeringDoNotVerifyRemoteGateways: true + remotePeeringUseRemoteGateways: false + } + ] + subnets: [ + { + name: avdVnetworkSubnetName + addressPrefix: avdVnetworkSubnetAddressPrefix + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Enabled' + networkSecurityGroupName: avdNetworksecurityGroupName + routeTableName: avdRouteTableName + } + ] + } + dependsOn: [ + avdNetworkObjectsRg + avdNetworksecurityGroup + avdApplicationSecurityGroup + avdRouteTable + ] +} + +// Update existing virtual network subnet (disable privete endpoint network policies). +/* +resource existingVnet 'Microsoft.Network/virtualNetworks@2021-05-01' existing = if (!empty(existingVnetSubnetResourceId)) { + name: existingVnetName + scope: resourceGroup('${existVnetSubsId}', '${existingVnetRgName}') +} + +resource existingSubnet 'Microsoft.Network/virtualNetworks/subnets@2021-05-01' existing = if (!empty(existingVnetSubnetResourceId)) { + name: existingSubnetName + parent: existingVnet +} + +module updateExistingSubnet '../carml/1.0.0/Microsoft.Network/virtualNetworks/subnets/deploy.bicep' = if (!empty(existingVnetSubnetResourceId)) { +scope: resourceGroup('${existVnetSubsId}', '${existingVnetRgName}') +name: 'Disable-NetworkPolicy-on-${existingSubnetName}-${time}' +params:{ + name: '${existingSubnetName}' + virtualNetworkName: existingVnetName + addressPrefix: existingSubnet.properties.addressPrefix + networkSecurityGroupName: !(empty(existingSubnet.properties.networkSecurityGroup.id)) ? split(string(existingSubnet.properties.networkSecurityGroup.id), '/')[8] : '' + networkSecurityGroupNameResourceGroupName: !(empty(existingSubnet.properties.networkSecurityGroup.id)) ? split(string(existingSubnet.properties.networkSecurityGroup.id), '/')[4] : '' + routeTableName: !(empty(existingSubnet.properties.routeTable.id)) ? split(string(existingSubnet.properties.routeTable.id), '/')[8] : '' + routeTableResourceGroupName: !(empty(existingSubnet.properties.routeTable.id)) ? split(string(existingSubnet.properties.routeTable.id), '/')[4] : '' + //serviceEndpointPolicies: existingSubnet.properties.serviceEndpointPolicies + privateEndpointNetworkPolicies: 'Disabled' + } +} +*/ + + +// =========== // +// Outputs // +// =========== // +output avdApplicationSecurityGroupResourceId string = avdApplicationSecurityGroup.outputs.resourceId +output avdVirtualNetworkResourceId string = avdVirtualNetwork.outputs.resourceId + + diff --git a/workload/bicep/avd-modules/avd-session-hosts.bicep b/workload/bicep/avd-modules/avd-session-hosts.bicep new file mode 100644 index 000000000..d323b5b86 --- /dev/null +++ b/workload/bicep/avd-modules/avd-session-hosts.bicep @@ -0,0 +1,228 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('AVD subnet ID') +param avdSubnetId string + +@description('Required. Location where to deploy compute services') +param avdSessionHostLocation string + +@description('AVD Session Host prefix') +param avdSessionHostNamePrefix string + +@description('Resource Group name for the session hosts') +param avdComputeObjectsRgName string + +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWorkloadSubsId string + +@description('Quantity of session hosts to deploy') +param avdDeploySessionHostsCount int + +@description('Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)') +param avdUseAvailabilityZones bool + +@description('Optional. Availablity Set name') +param avdAvailabilitySetName string + +@description('Optional. Sets the number of fault domains for the availability set. (Defualt: 3)') +param avdAsFaultDomainCount int + +@description('Optional. Sets the number of update domains for the availability set. (Defualt: 5)') +param avdAsUpdateDomainCount int + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool + +@description('Session host VM size (Defualt: Standard_D2s_v3) ') +param avdSessionHostsSize string + +@description('OS disk type for session host (Defualt: Standard_LRS) ') +param avdSessionHostDiskType string + +@description('Market Place OS image') +param marketPlaceGalleryWindows object + +@description('Set to deploy image from Azure Compute Gallery') +param useSharedImage bool + +@description('Source custom image ID') +param avdImageTemplataDefinitionId string + +@description('Fslogix Managed Identity Resource ID ') +param fslogixManagedIdentityResourceId string + +@description('Local administrator username') +param avdVmLocalUserName string + +@description('Local administrator password') +@secure() +param avdVmLocalUserPassword string + +@description('Required. AD domain name') +param avdIdentityDomainName string + +@description('Required. AVD session host domain join credentials') +param avdDomainJoinUserName string +@secure() +param avdDomainJoinUserPassword string + +@description('Optional. OU path to join AVd VMs') +param avdOuPath string + +@description('Application Security Group (ASG) for the session hosts') +param avdApplicationSecurityGroupResourceId string + +@description('AVD host pool token') +param hostPoolToken string + +@description('AVD Host Pool name') +param avdHostPoolName string + +@description('Location for the AVD agent installation package. ') +param avdAgentPackageLocation string + +@description('FSlogix configuration script file name. ') +param fsLogixScript string + +@description('Configuration arguments for FSlogix') +param FsLogixScriptArguments string + +@description('URI for FSlogix configuration script') +param fslogixScriptUri string + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Variable declaration // +// =========== // +var allAvailabilityZones = pickZones('Microsoft.Compute', 'virtualMachines', avdSessionHostLocation, 3) + +// =========== // +// Deployments // +// =========== // + +// Availability set. +module avdAvailabilitySet '../../../carml/1.2.0/Microsoft.Compute/availabilitySets/deploy.bicep' = if (!avdUseAvailabilityZones) { + name: 'AVD-Availability-Set-${time}' + scope: resourceGroup('${avdWorkloadSubsId}', '${avdComputeObjectsRgName}') + params: { + name: avdAvailabilitySetName + location: avdSessionHostLocation + availabilitySetFaultDomain: avdAsFaultDomainCount + availabilitySetUpdateDomain: avdAsUpdateDomainCount + } +} + +// Session hosts. +module avdSessionHosts '../../../carml/1.2.0/Microsoft.Compute/virtualMachines/deploy.bicep' = [for i in range(0, avdDeploySessionHostsCount): { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdComputeObjectsRgName}') + name: 'AVD-Session-Host-${i}-${time}' + params: { + name: '${avdSessionHostNamePrefix}-${i}' + location: avdSessionHostLocation + userAssignedIdentities: { + '${fslogixManagedIdentityResourceId}' : {} + } + availabilityZone: avdUseAvailabilityZones ? take(skip(allAvailabilityZones, i % length(allAvailabilityZones)), 1) : [] + encryptionAtHost: encryptionAtHost + availabilitySetName: !avdUseAvailabilityZones ? avdAvailabilitySet.outputs.name : '' + osType: 'Windows' + licenseType: 'Windows_Client' + vmSize: avdSessionHostsSize + imageReference: useSharedImage ? json('{\'id\': \'${avdImageTemplataDefinitionId}\'}') : marketPlaceGalleryWindows + osDisk: { + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: 128 + managedDisk: { + storageAccountType: avdSessionHostDiskType + } + } + adminUsername: avdVmLocalUserName + adminPassword: avdVmLocalUserPassword //avdWrklKeyVaultget.getSecret('avdVmLocalUserPassword') //avdVmLocalUserPassword // need to update to get value from KV + nicConfigurations: [ + { + nicSuffix: '-nic-01' + deleteOption: 'Delete' + asgId: !empty(avdApplicationSecurityGroupResourceId) ? avdApplicationSecurityGroupResourceId : null + enableAcceleratedNetworking: false + ipConfigurations: [ + { + name: 'ipconfig01' + subnetId: avdSubnetId + } + ] + } + ] + // Join domain. + allowExtensionOperations: true + extensionDomainJoinPassword: avdDomainJoinUserPassword //avdWrklKeyVaultget.getSecret('avdDomainJoinUserPassword') + extensionDomainJoinConfig: { + enabled: true + settings: { + name: avdIdentityDomainName + ouPath: !empty(avdOuPath) ? avdOuPath : null + user: avdDomainJoinUserName + restart: 'true' + options: '3' + } + } + // Enable and Configure Microsoft Malware. + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + isEnabled: 'true' + day: '7' // Day of the week for scheduled scan (1-Sunday, 2-Monday, ..., 7-Saturday) + time: '120' // When to perform the scheduled scan, measured in minutes from midnight (0-1440). For example: 0 = 12AM, 60 = 1AM, 120 = 2AM. + scanType: 'Quick' //Indicates whether scheduled scan setting type is set to Quick or Full (default is Quick) + } + Exclusions: { + Extensions: '*.vhd;*.vhdx' + Paths: '"%ProgramFiles%\\FSLogix\\Apps\\frxdrv.sys;%ProgramFiles%\\FSLogix\\Apps\\frxccd.sys;%ProgramFiles%\\FSLogix\\Apps\\frxdrvvt.sys;%TEMP%\\*.VHD;%TEMP%\\*.VHDX;%Windir%\\TEMP\\*.VHD;%Windir%\\TEMP\\*.VHDX;\\\\server\\share\\*\\*.VHD;\\\\server\\share\\*\\*.VHDX' + Processes: '%ProgramFiles%\\FSLogix\\Apps\\frxccd.exe;%ProgramFiles%\\FSLogix\\Apps\\frxccds.exe;%ProgramFiles%\\FSLogix\\Apps\\frxsvc.exe' + } + } + } + } + dependsOn: [] + }] + +// Add session hosts to AVD Host pool. +module addAvdHostsToHostPool '../../vm-custom-extensions/add-avd-session-hosts.bicep' = [for i in range(0, avdDeploySessionHostsCount): { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdComputeObjectsRgName}') + name: 'Add-AVD-Session-Host-${i}-to-HostPool-${time}' + params: { + location: avdSessionHostLocation + hostPoolToken: hostPoolToken + name: '${avdSessionHostNamePrefix}-${i}' + hostPoolName: avdHostPoolName + avdAgentPackageLocation: avdAgentPackageLocation + } + dependsOn: [ + avdSessionHosts +] +}] + + +// Add the registry keys for Fslogix. Alternatively can be enforced via GPOs. +module configureFsLogixForAvdHosts '../../vm-custom-extensions/configure-fslogix-session-hosts.bicep' = [for i in range(0, avdDeploySessionHostsCount): { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdComputeObjectsRgName}') + name: 'Configure-FsLogix-for-${avdSessionHostNamePrefix}-${i}-${time}' + params: { + location: avdSessionHostLocation + name: '${avdSessionHostNamePrefix}-${i}' + file: fsLogixScript + FsLogixScriptArguments: FsLogixScriptArguments + baseScriptUri: fslogixScriptUri + } + dependsOn: [ + avdSessionHosts + ] +}] diff --git a/workload/bicep/avd-modules/avd-storage-azurefiles.bicep b/workload/bicep/avd-modules/avd-storage-azurefiles.bicep new file mode 100644 index 000000000..7bf71c4dc --- /dev/null +++ b/workload/bicep/avd-modules/avd-storage-azurefiles.bicep @@ -0,0 +1,223 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Resource Group name for the session hosts') +param avdComputeObjectsRgName string + +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWorkloadSubsId string + +@description('Resource Group Name for Azure Files') +param avdStorageObjectsRgName string + +@description('AVD subnet ID') +param avdSubnetId string + +@description('Required. Location where to deploy compute services') +param avdSessionHostLocation string + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool + +@description('Session host VM size (Defualt: Standard_D2s_v3) ') +param avdSessionHostsSize string + +@description('OS disk type for session host (Defualt: Standard_LRS) ') +param avdSessionHostDiskType string + +@description('Market Place OS image') +param marketPlaceGalleryWindows object + +@description('Set to deploy image from Azure Compute Gallery') +param useSharedImage bool + +@description('Source custom image ID') +param avdImageTemplataDefinitionId string + +@description('Fslogix Managed Identity Resource ID ') +param fslogixManagedIdentityResourceId string + +@description('Subnet resource ID for the Azure Files private endpoint') +param subnetResourceId string + +@description('Local administrator username') +param avdVmLocalUserName string + +@description('Local administrator password') +@secure() +param avdVmLocalUserPassword string + +@description('Required. AD domain name') +param avdIdentityDomainName string + +@description('Required. AVD session host domain join credentials') +param avdDomainJoinUserName string + +@secure() +param avdDomainJoinUserPassword string + +@description('Optional. OU path to join AVd VMs') +param avdOuPath string + +@description('Application Security Group (ASG) for the session hosts') +param avdApplicationSecurityGroupResourceId string + +@description('Azure Fies storage account name') +param avdFslogixStorageName string + +@description('Azure Files share name') +param avdFslogixFileShareName string + +@description('Azure Files storage account SKU') +param fsLogixStorageSku string + +@description('Azure File share quota') +param avdFslogixFileShareQuotaSize int + +@description('Use Azure private DNS zones for private endpoints (Default: false)') +param avdVnetPrivateDnsZone bool + +@description('Use Azure private DNS zones for private endpoints (Default: false)') +param avdVnetPrivateDnsZoneFilesId string + +@description('Name for temporary virtual machine. Used to join Azure Files to domain') +param tempStorageVmName string + +@description('Script name for adding storage account to Active Directory') +param addStorageToDomainScript string + +@description('Script arguments for adding the storage account to Active Directory') +param addStorageToDomainScriptArgs string + +@description('URI for the script for adding the storage account to Active Directory') +param addStorageToDomainScriptUri string + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Deployments // +// =========== // + +// Provision the storage account and Azure Files. +module fslogixStorage '../../../carml/1.2.0/Microsoft.Storage/storageAccounts/deploy.bicep' = { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdStorageObjectsRgName}') + name: 'AVD-Fslogix-Storage-${time}' + params: { + name: avdFslogixStorageName + location: avdSessionHostLocation + storageAccountSku: fsLogixStorageSku + allowBlobPublicAccess: false + storageAccountKind: ((fsLogixStorageSku =~ 'Premium_LRS') || (fsLogixStorageSku =~ 'Premium_ZRS')) ? 'FileStorage': 'StorageV2' + storageAccountAccessTier: 'Hot' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + virtualNetworkRules: [] + ipRules: [] + } + fileServices: { + shares: [ + { + name: avdFslogixFileShareName + shareQuota: avdFslogixFileShareQuotaSize * 100 //Portal UI steps scale + } + ] + } + privateEndpoints: avdVnetPrivateDnsZone ? [ + { + subnetResourceId: subnetResourceId + service: 'file' + privateDnsZoneResourceIds: [ + avdVnetPrivateDnsZoneFilesId + ] + } + ] :[ + { + subnetResourceId: subnetResourceId + service: 'file' + } + ] + } +} + +// Provision temporary VM and add it to domain. +module storageVM '../../../carml/1.2.0/Microsoft.Compute/virtualMachines/deploy.bicep' = { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdStorageObjectsRgName}') + name: 'Deploy-temporary-VM-FsLogixStorageToDomain-${time}' + params: { + name: tempStorageVmName + location: avdSessionHostLocation + userAssignedIdentities: { + '${fslogixManagedIdentityResourceId}' : {} + } + encryptionAtHost: encryptionAtHost + availabilityZone: [] + osType: 'Windows' + licenseType: 'Windows_Client' + vmSize: avdSessionHostsSize + imageReference: useSharedImage ? json('{\'id\': \'${avdImageTemplataDefinitionId}\'}') : marketPlaceGalleryWindows + osDisk: { + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: 128 + managedDisk: { + storageAccountType: avdSessionHostDiskType + } + } + adminUsername: avdVmLocalUserName + adminPassword: avdVmLocalUserPassword + nicConfigurations: [ + { + nicSuffix: '-nic-01' + deleteOption: 'Delete' + asgId: !empty(avdApplicationSecurityGroupResourceId) ? avdApplicationSecurityGroupResourceId : null + enableAcceleratedNetworking: false + ipConfigurations: [ + { + name: 'ipconfig01' + subnetId: avdSubnetId + } + ] + } + ] + // Join domain + allowExtensionOperations: true + extensionDomainJoinPassword: avdDomainJoinUserPassword + extensionDomainJoinConfig: { + enabled: true + settings: { + name: avdIdentityDomainName + ouPath: !empty(avdOuPath) ? avdOuPath : null + user: avdDomainJoinUserName + restart: 'true' + options: '3' + } + } + } + dependsOn: [ + fslogixStorage + ] +} + +// Custom Extension call in on the DSC script to join Azure storage account to domain. +module addFslogixShareToADDSSript '../../vm-custom-extensions/add-azure-files-to-adds-script.bicep' = { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdStorageObjectsRgName}') + name: 'Add-FslogixStorage-to-ADDS-${time}' + params: { + location: avdSessionHostLocation + name: storageVM.outputs.name + file: addStorageToDomainScript + ScriptArguments: addStorageToDomainScriptArgs + baseScriptUri: addStorageToDomainScriptUri + } + dependsOn: [ + fslogixStorage + storageVM + ] +} + + // Run deployment script to remove the VM --> 0.2 release. + // needs user managed identity --> Virtual machine contributor role assignment. Deployment script to assume the identity to delete VM. Include NIC and disks (force) diff --git a/workload/bicep/deploy-baseline.bicep b/workload/bicep/deploy-baseline.bicep new file mode 100644 index 000000000..755890984 --- /dev/null +++ b/workload/bicep/deploy-baseline.bicep @@ -0,0 +1,506 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@minLength(2) +@maxLength(4) +@description('Required. The name of the resource group to deploy') +param deploymentPrefix string = '' + +@description('Required. Location where to deploy compute services') +param avdSessionHostLocation string = '' + +@description('Required. Location where to deploy AVD management plane') +param avdManagementPlaneLocation string = '' + +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWorkloadSubsId string = '' + +@description('Azure Virtual Desktop Enterprise Application object ID. ') +param avdEnterpriseAppObjectId string = '' + +@description('Required. AVD session host local credentials') +param avdVmLocalUserName string = '' +@secure() +param avdVmLocalUserPassword string = '' + +@description('Required. AD domain name') +param avdIdentityDomainName string = '' + +@description('Required. AVD session host domain join credentials') +param avdDomainJoinUserName string = '' +@secure() +param avdDomainJoinUserPassword string = '' + +@description('Optional. OU path to join AVd VMs') +param avdOuPath string = '' +/* +@description('Optional. Id to grant access to on AVD workload key vault secrets') +param avdWrklSecretAccess string = '' +*/ +@allowed([ + 'Personal' + 'Pooled' +]) +@description('Optional. AVD host pool type (Default: Pooled)') +param avdHostPoolType string = 'Pooled' + +@allowed([ + 'Automatic' + 'Direct' +]) +@description('Optional. AVD host pool type (Default: Automatic)') +param avdPersonalAssignType string = 'Automatic' + +@allowed([ + 'BreadthFirst' + 'DepthFirst' +]) +@description('Required. AVD host pool load balacing type (Default: BreadthFirst)') +param avdHostPoolLoadBalancerType string = 'BreadthFirst' + +@description('Optional. AVD host pool maximum number of user sessions per session host') +param avhHostPoolMaxSessions int = 15 + +@description('Optional. AVD host pool start VM on Connect') +param avdStartVmOnConnect bool + +@description('Create custom Start VM on connect role') +param createStartVmOnConnectCustomRole bool + +@description('Optional. AVD deploy remote app application group') +param avdDeployRappGroup bool + +@description('Optional. AVD host pool Custom RDP properties') +param avdHostPoolRdpProperties string = 'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2' + +@description('Create new virtual network') +param createAvdVnet bool + +@description('Existing virtual network subnet') +param existingVnetSubnetResourceId string = '' + +@description('Existing hub virtual network for perring') +param existingHubVnetResourceId string = '' + +@description('AVD virtual network address prefixes') +param avdVnetworkAddressPrefixes string = '' + +@description('AVD virtual network subnet address prefix') +param avdVnetworkSubnetAddressPrefix string = '' + +@description('custom DNS servers IPs') +param customDnsIps string = '' + +@description('Use Azure private DNS zones for private endpoints (Default: false)') +param avdVnetPrivateDnsZone bool = false + +@description('Use Azure private DNS zones for private endpoints (Default: false)') +param avdVnetPrivateDnsZoneFilesId string = '' + +@description('Use Azure private DNS zones for private endpoints (Default: false)') +param avdVnetPrivateDnsZoneKeyvaultId string = '' + +@description('Does the hub contains a virtual network gateway') +param vNetworkGatewayOnHub bool + +@description('Optional. Fslogix file share size (Default: 5TB)') +param avdFslogixFileShareQuotaSize int = 512 + +@description('Deploy new session hosts') +param avdDeploySessionHosts bool + +@minValue(1) +@maxValue(49) +@description('Cuantity of session hosts to deploy') +param avdDeploySessionHostsCount int + +@description('Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)') +param avdUseAvailabilityZones bool = true + +@description('Optional. Sets the number of fault domains for the availability set. (Defualt: 3)') +param avdAsFaultDomainCount int = 2 + +@description('Optional. Sets the number of update domains for the availability set. (Defualt: 5)') +param avdAsUpdateDomainCount int = 5 + +@description('Storage account SKU for FSLogix storage. Recommended tier is Premium LRS or Premium ZRS (where available)') +param fsLogixStorageSku string = '' + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool = false + +@description('Session host VM size (Defualt: Standard_D2s_v3) ') +param avdSessionHostsSize string = 'Standard_D2s_v3' + +@description('OS disk type for session host (Defualt: Standard_LRS) ') +param avdSessionHostDiskType string = 'Standard_LRS' + + +@allowed([ + 'win10_21h2_office' + 'win10_21h2' + 'win11_21h2_office' + 'win11_21h2' +]) +@description('Required. AVD OS image source (Default: win10-21h2)') +param avdOsImage string = 'win10_21h2' + +@description('Set to deploy image from Azure Compute Gallery') +param useSharedImage bool + +@description('Source custom image ID') +param avdImageTemplataDefinitionId string = '' + +@description('OU name for Azure Storage Account. It is recommended to create a new AD Organizational Unit (OU) in AD and disable password expiration policy on computer accounts or service logon accounts accordingly. ') +param storageOuName string = '' + +@description('If OU for Azure Storage needs to be created - set to true and ensure the domain join credentials have priviledge to create OU and create computer objects or join to domain') +param createOuForStorage bool = false + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Variable declaration // +// =========== // +var deploymentPrefixLowercase = toLower(deploymentPrefix) +var avdSessionHostLocationLowercase = toLower(avdSessionHostLocation) +var avdManagementPlaneLocationLowercase = toLower(avdManagementPlaneLocation) +var avdServiceObjectsRgName = 'rg-${avdManagementPlaneLocationLowercase}-avd-${deploymentPrefixLowercase}-service-objects' // max length limit 90 characters +var avdNetworkObjectsRgName = 'rg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}-network' // max length limit 90 characters +var avdComputeObjectsRgName = 'rg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}-pool-compute' // max length limit 90 characters +var avdStorageObjectsRgName = 'rg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}-storage' // max length limit 90 characters +var avdSharedResourcesRgName = 'rg-${avdSessionHostLocationLowercase}-avd-shared-resources' +var avdVnetworkName = 'avdvnet-${avdSessionHostLocationLowercase}-${deploymentPrefixLowercase}' +var avdVnetworkSubnetName = 'avd-${deploymentPrefixLowercase}' +var avdNetworksecurityGroupName = 'avdnsg-${avdSessionHostLocationLowercase}-${deploymentPrefixLowercase}' +var avdRouteTableName = 'avdudr-${avdSessionHostLocationLowercase}-${deploymentPrefixLowercase}' +var avdApplicationsecurityGroupName = 'avdasg-${avdSessionHostLocationLowercase}-${deploymentPrefixLowercase}' +var avdVnetworkPeeringName = '${uniqueString(deploymentPrefixLowercase, avdSessionHostLocation)}-peering-avd-${deploymentPrefixLowercase}' +var avdWorkSpaceName = 'avdws-${deploymentPrefixLowercase}' +var avdHostPoolName = 'avdhp-${deploymentPrefixLowercase}' +var avdApplicationGroupNameDesktop = 'avddag-${deploymentPrefixLowercase}' +var avdApplicationGroupNameRapp = 'avdraag-${deploymentPrefixLowercase}' +var marketPlaceGalleryWindows = { + 'win10_21h2_office': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'office-365' + sku: 'win10-21h2-avd-m365' + version: 'latest' + } + + 'win10_21h2': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'windows-10' + sku: 'win10-21h2-avd' + version: 'latest' + } + + 'win11_21h2_office': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'office-365' + sku: 'win11-21h2-avd-m365' + version: 'latest' + } + + 'win11_21h2': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'Windows-11' + sku: 'win11-21h2-avd' + version: 'latest' + } +} + +var baseScriptUri = 'https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/' +var fslogixScriptUri = '${baseScriptUri}scripts/Set-FSLogixRegKeys.ps1' +var fsLogixScript = './Set-FSLogixRegKeys.ps1' +var fslogixSharePath = '\\\\${avdFslogixStorageName}.file.${environment().suffixes.storage}\\${avdFslogixFileShareName}' +var FsLogixScriptArguments = '-volumeshare ${fslogixSharePath}' +var fslogixManagedIdentityName = 'avd-uai-fslogix' +var avdAgentPackageLocation = 'https://wvdportalstorageblob.blob.${environment().suffixes.storage}/galleryartifacts/Configuration_01-20-2022.zip' +var avdFslogixStorageName = take('fslogix${uniqueString(deploymentPrefixLowercase, avdSessionHostLocationLowercase)}${deploymentPrefixLowercase}',15) +var avdFslogixFileShareName = 'fslogix-${deploymentPrefixLowercase}' +var storageAccountContributorRoleId='b24988ac-6180-42a0-ab88-20f7382dd24c' +var readerRoleId = 'acdd72a7-3385-48ef-bd42-f606fba81ae7' +var tempStorageVmName='tempstgvm' +var dscAgentPackageLocation = 'https://github.com/Azure/avdaccelerator/raw/main/workload/scripts/DSCDomainJoinStorageScripts.zip' +var addStorageToDomainScriptUri='${baseScriptUri}scripts/Manual-DSC-JoinStorage-to-ADDS.ps1' +var addStorageToDomainScript='./Manual-DSC-JoinStorage-to-ADDS.ps1' +var addStorageToDomainScriptArgs='-DscPath ${dscAgentPackageLocation} -StorageAccountName ${avdFslogixStorageName} -StorageAccountRG ${avdStorageObjectsRgName} -DomainName ${avdIdentityDomainName} -AzureCloudEnvironment AzureCloud -DomainAdminUserName ${avdDomainJoinUserName} -DomainAdminUserPassword ${avdDomainJoinUserPassword} -OUName ${OuStgName} -CreateNewOU ${createOuForStorageString} -ShareName ${avdFslogixFileShareName} -Verbose' +var OuStgName = !empty(storageOuName)? storageOuName : 'Computers' +var avdWrklKvName = 'avd-${uniqueString(deploymentPrefixLowercase, avdSessionHostLocationLowercase)}-${deploymentPrefixLowercase}' // max length limit 24 characters +var avdSessionHostNamePrefix = 'avdsh-${deploymentPrefix}' +var avdAvailabilitySetName = 'avdas-${deploymentPrefix}' +var allAvailabilityZones = pickZones('Microsoft.Compute', 'virtualMachines', avdSessionHostLocation, 3) +var createOuForStorageString = string(createOuForStorage) + +var resourceGroups = [ + { + name: avdServiceObjectsRgName + location: avdManagementPlaneLocation + } + { + name: avdComputeObjectsRgName + location: avdSessionHostLocation + } + { + name: avdStorageObjectsRgName + location: avdSessionHostLocation + } +] +// =========== // +// Deployments // +// =========== // + +// Resource groups. +module avdBaselineResourceGroups '../../carml/1.2.0/Microsoft.Resources/resourceGroups/deploy.bicep' = [ for resourceGroup in resourceGroups: { + scope: subscription(avdWorkloadSubsId) + name: 'Deploy-${substring(resourceGroup.name,10)}-${time}' + params: { + name: resourceGroup.name + location: resourceGroup.location + enableDefaultTelemetry: false + } +}] + +// Optional. Networking. +module avdNetworking 'avd-modules/avd-networking.bicep' = if (createAvdVnet) { + name: 'Deploy-AVD-Networking-${time}' + params: { + avdApplicationsecurityGroupName: avdApplicationsecurityGroupName + avdComputeObjectsRgName: avdComputeObjectsRgName + avdNetworkObjectsRgName: avdNetworkObjectsRgName + avdNetworksecurityGroupName: avdNetworksecurityGroupName + avdRouteTableName: avdRouteTableName + avdVnetworkAddressPrefixes: avdVnetworkAddressPrefixes + avdVnetworkName: avdVnetworkName + avdVnetworkPeeringName: avdVnetworkPeeringName + avdVnetworkSubnetName: avdVnetworkSubnetName + createAvdVnet: createAvdVnet + vNetworkGatewayOnHub: vNetworkGatewayOnHub + existingHubVnetResourceId: existingHubVnetResourceId + avdSessionHostLocation: avdSessionHostLocation + avdVnetworkSubnetAddressPrefix: avdVnetworkSubnetAddressPrefix + avdWorkloadSubsId:avdWorkloadSubsId + customDnsIps: customDnsIps + } + dependsOn: [ + avdBaselineResourceGroups + ] +} + +// AVD management plane. +module avdHostPoolandAppGroups 'avd-modules/avd-hostpool-app-groups.bicep' = { + name: 'Deploy-AVD-HostPool-AppGroups-${time}' + params: { + avdApplicationGroupNameDesktop: avdApplicationGroupNameDesktop + avdApplicationGroupNameRapp: avdApplicationGroupNameRapp + avdDeployRappGroup: avdDeployRappGroup + avdHostPoolName: avdHostPoolName + avdHostPoolRdpProperties: avdHostPoolRdpProperties + avdHostPoolLoadBalancerType: avdHostPoolLoadBalancerType + avdHostPoolType: avdHostPoolType + avhHostPoolMaxSessions:avhHostPoolMaxSessions + avdPersonalAssignType: avdPersonalAssignType + avdManagementPlaneLocation: avdManagementPlaneLocation + avdServiceObjectsRgName: avdServiceObjectsRgName + avdStartVmOnConnect: avdStartVmOnConnect + avdWorkloadSubsId: avdWorkloadSubsId + } + dependsOn: [ + avdBaselineResourceGroups + ] +} + +module avdWorkSpace '../../carml/1.2.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep' = { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdServiceObjectsRgName}') + name: 'Deploy-AVD-WorkSpace-${time}' + params: { + name: avdWorkSpaceName + location: avdManagementPlaneLocation + appGroupResourceIds: avdHostPoolandAppGroups.outputs.avdAppGroupsArray + } + dependsOn: [ + avdHostPoolandAppGroups + ] +} +// + +// Identity: managed identities and role assignments. +module deployAvdManagedIdentitiesRoleAssign 'avd-modules/avd-identity.bicep' = { + name: 'Create-ManagedIdentities-RoleAssign' + params: { + avdComputeObjectsRgName: avdComputeObjectsRgName + avdDeploySessionHosts: avdDeploySessionHosts + avdEnterpriseAppObjectId: avdEnterpriseAppObjectId + avdManagementPlaneLocation: avdManagementPlaneLocation + avdServiceObjectsRgName: avdServiceObjectsRgName + avdStorageObjectsRgName: avdStorageObjectsRgName + avdWorkloadSubsId: avdWorkloadSubsId + createStartVmOnConnectCustomRole: createStartVmOnConnectCustomRole + fslogixManagedIdentityName: fslogixManagedIdentityName + readerRoleId: readerRoleId + storageAccountContributorRoleId: storageAccountContributorRoleId + } + dependsOn:[ + avdBaselineResourceGroups + ] +} + +// Key vault. +module avdWrklKeyVault '../../carml/1.2.0/Microsoft.KeyVault/vaults/deploy.bicep' = if (avdDeploySessionHosts) { + scope: resourceGroup('${avdWorkloadSubsId}', '${avdServiceObjectsRgName}') + name: 'AVD-Workload-KeyVault-${time}' + params: { + name: avdWrklKvName + location: avdSessionHostLocation + enableRbacAuthorization: false + enablePurgeProtection: true + softDeleteRetentionInDays: 7 + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + virtualNetworkRules: [] + ipRules: [] + } + privateEndpoints: avdVnetPrivateDnsZone ? [ + { + subnetResourceId: createAvdVnet ? '${avdNetworking.outputs.avdVirtualNetworkResourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + service: 'vault' + privateDnsZoneResourceIds: [ + avdVnetPrivateDnsZoneKeyvaultId + ] + } + ] :[ + { + subnetResourceId: createAvdVnet ? '${avdNetworking.outputs.avdVirtualNetworkResourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + service: 'vault' + } + ] + secrets: { + secureList: [ + { + name: 'avdVmLocalUserPassword' + value: avdVmLocalUserPassword + contentType: 'Session host local user credentials' + } + { + name: 'avdVmLocalUserName' + value: avdVmLocalUserName + contentType: 'Session host local user credentials' + } + { + name: 'avdDomainJoinUserName' + value: avdDomainJoinUserName + contentType: 'Domain join credentials' + } + { + name: 'avdDomainJoinUserPassword' + value: avdDomainJoinUserPassword + contentType: 'Domain join credentials' + } + ] + } + } + dependsOn: [ + avdBaselineResourceGroups + //updateExistingSubnet + ] +} +// + +// Call on the KV. +resource avdWrklKeyVaultget 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = if (avdDeploySessionHosts) { + name: avdWrklKvName + scope: resourceGroup('${avdWorkloadSubsId}', '${avdServiceObjectsRgName}') +} + +// Storage. +module deployAvdStorageAzureFiles 'avd-modules/avd-storage-azurefiles.bicep' = if (avdDeploySessionHosts) { + name: 'Deploy-AVD-Storage-AzureFiles-${time}' + params: { + addStorageToDomainScript: addStorageToDomainScript + addStorageToDomainScriptArgs: addStorageToDomainScriptArgs + addStorageToDomainScriptUri: addStorageToDomainScriptUri + avdApplicationSecurityGroupResourceId: createAvdVnet ? '${avdNetworking.outputs.avdApplicationSecurityGroupResourceId}' : '' + avdComputeObjectsRgName: avdComputeObjectsRgName + avdDomainJoinUserName: avdDomainJoinUserName + //avdDomainJoinUserPassword: avdDomainJoinUserPassword + avdDomainJoinUserPassword: avdWrklKeyVaultget.getSecret('avdDomainJoinUserPassword') + avdFslogixFileShareName: avdFslogixFileShareName + avdFslogixFileShareQuotaSize: avdFslogixFileShareQuotaSize + avdFslogixStorageName: avdFslogixStorageName + avdIdentityDomainName: avdIdentityDomainName + avdImageTemplataDefinitionId: avdImageTemplataDefinitionId + avdOuPath: avdOuPath + avdSessionHostDiskType: avdSessionHostDiskType + avdSessionHostLocation: avdSessionHostLocation + avdSessionHostsSize: avdSessionHostsSize + avdStorageObjectsRgName: avdStorageObjectsRgName + avdSubnetId: createAvdVnet ? '${avdNetworking.outputs.avdVirtualNetworkResourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + avdVmLocalUserName: avdVmLocalUserName + //avdVmLocalUserPassword: avdVmLocalUserPassword + avdVmLocalUserPassword: avdWrklKeyVaultget.getSecret('avdVmLocalUserPassword') + avdVnetPrivateDnsZone: avdVnetPrivateDnsZone + avdVnetPrivateDnsZoneFilesId: avdVnetPrivateDnsZoneFilesId + avdWorkloadSubsId: avdWorkloadSubsId + encryptionAtHost: encryptionAtHost + fslogixManagedIdentityResourceId: deployAvdManagedIdentitiesRoleAssign.outputs.fslogixManagedIdentityResourceId + fsLogixStorageSku: fsLogixStorageSku + marketPlaceGalleryWindows: marketPlaceGalleryWindows['win10_21h2'] + subnetResourceId: createAvdVnet ? '${avdNetworking.outputs.avdVirtualNetworkResourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + tempStorageVmName: tempStorageVmName + useSharedImage: useSharedImage + } + dependsOn:[ + avdBaselineResourceGroups + avdNetworking + avdWrklKeyVaultget + ] +} + +// Session hosts. +module deployAndConfigureAvdSessionHosts 'avd-modules/avd-session-hosts.bicep' = if (avdDeploySessionHosts) { + name: 'Deploy-and-Configure-AVD-SessionHosts-${time}' + params: { + avdAgentPackageLocation: avdAgentPackageLocation + avdApplicationSecurityGroupResourceId: createAvdVnet ? '${avdNetworking.outputs.avdApplicationSecurityGroupResourceId}' : '' + avdAsFaultDomainCount: avdAsFaultDomainCount + avdAsUpdateDomainCount: avdAsUpdateDomainCount + avdAvailabilitySetName: avdAvailabilitySetName + avdComputeObjectsRgName: avdComputeObjectsRgName + avdDeploySessionHostsCount: avdDeploySessionHostsCount + avdDomainJoinUserName: avdDomainJoinUserName + //avdDomainJoinUserPassword: avdDomainJoinUserPassword + avdDomainJoinUserPassword: avdWrklKeyVaultget.getSecret('avdDomainJoinUserPassword') + avdHostPoolName: avdHostPoolName + avdIdentityDomainName: avdIdentityDomainName + avdImageTemplataDefinitionId: avdImageTemplataDefinitionId + avdOuPath: avdOuPath + avdSessionHostDiskType: avdSessionHostDiskType + avdSessionHostLocation: avdSessionHostLocation + avdSessionHostNamePrefix: avdSessionHostNamePrefix + avdSessionHostsSize: avdSessionHostsSize + avdSubnetId: createAvdVnet ? '${avdNetworking.outputs.avdVirtualNetworkResourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + avdUseAvailabilityZones: avdUseAvailabilityZones + avdVmLocalUserName: avdVmLocalUserName + //avdVmLocalUserPassword: avdVmLocalUserPassword + avdVmLocalUserPassword: avdWrklKeyVaultget.getSecret('avdVmLocalUserPassword') + avdWorkloadSubsId: avdWorkloadSubsId + encryptionAtHost: encryptionAtHost + fslogixManagedIdentityResourceId: deployAvdManagedIdentitiesRoleAssign.outputs.fslogixManagedIdentityResourceId + fsLogixScript: fsLogixScript + FsLogixScriptArguments: FsLogixScriptArguments + fslogixScriptUri: fslogixScriptUri + hostPoolToken: avdHostPoolandAppGroups.outputs.hostPooltoken + marketPlaceGalleryWindows: marketPlaceGalleryWindows[avdOsImage] + useSharedImage: useSharedImage + } + dependsOn: [ + avdBaselineResourceGroups + avdNetworking + avdWrklKeyVaultget + ] +} diff --git a/workload/bicep/deploy-custom-image.bicep b/workload/bicep/deploy-custom-image.bicep new file mode 100644 index 000000000..fd58e92ae --- /dev/null +++ b/workload/bicep/deploy-custom-image.bicep @@ -0,0 +1,503 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@minLength(2) +@maxLength(4) +@description('Required. The name of the resource group to deploy') +param deploymentPrefix string = '' + +@description('Required. Location where to deploy compute services') +param avdSharedServicesLocation string = '' + +@description('Optional. AVD shared services subscription ID, multiple subscriptions scenario') +param avdSharedServicesSubId string = '' + +@description('Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)') +param avdUseAvailabilityZones bool + +@allowed([ + 'eastus' + 'eastus2' + 'westcentralus' + 'westus' + 'westus2' + 'westus3' + 'southcentralus' + 'northeurope' + 'westeurope' + 'southeastasia' + 'australiasoutheast' + 'australiaeast' + 'uksouth' + 'ukwest' +]) +@description('Azure image builder location (Defualt: eastus2)') +param aibLocation string = 'eastus2' + +@description('Create custom azure image builder role') +param createAibCustomRole bool + +@allowed([ + 'win10_21h2_office' + 'win10_21h2' + 'win11_21h2_office' + 'win11_21h2' +]) +@description('Required. AVD OS image source (Default: win10-21h2)') +param avdOsImage string = 'win10_21h2' + +@description('Set to deploy image from Azure Compute Gallery') +param useSharedImage bool = true + +@description('Create azure image Builder managed identity') +param createAibManagedIdentity bool + +@description('Select existing azure image Builder managed identity') +param existingAibManagedIdentityId string + +@description('Select existing azure image Builder managed identity') +param existingAibManagedIdentityName string + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Variable declaration // +// =========== // +var deploymentPrefixLowercase = toLower(deploymentPrefix) +var avdSharedServicesLocationLowercase = toLower(avdSharedServicesLocation) +var avdSharedResourcesRgName = 'rg-${avdSharedServicesLocationLowercase}-avd-shared-resources' +var imageGalleryName = 'avdgallery${avdSharedServicesLocationLowercase}' +var aibManagedIdentityName = 'avd-uai-aib' +var deployScriptManagedIdentityName = 'avd-uai-deployScript' +var imageDefinitionsTemSpecName = 'AVDImageDefinition_${avdOsImage}' +var imageVmSize = 'Standard_D4s_v3' +var avdOsImageDefinitions = { + 'win10_21h2_office': { + name: 'Windows10_21H2_Office' + osType: 'Windows' + osState: 'Generalized' + offer: 'office-365' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win10-21h2-avd-m365' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V1' + } + 'win10_21h2': { + name: 'Windows10_21H2' + osType: 'Windows' + osState: 'Generalized' + offer: 'windows-10' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win10-21h2-avd' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V1' + } + 'win11_21h2_office': { + name: 'Windows11_21H2' + osType: 'Windows' + osState: 'Generalized' + offer: 'office-365' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win11-21h2-avd-m365' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V2' + } + 'win11_21h2': { + name: 'Windows11_21H2' + osType: 'Windows' + osState: 'Generalized' + offer: 'windows-11' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win11-21h2-avd' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V2' + } +} +var baseScriptUri = 'https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/' +var avdSharedSResourcesStorageName = 'avd${uniqueString(deploymentPrefixLowercase, avdSharedServicesLocationLowercase)}shared' +var avdSharedSResourcesAibContainerName = 'aib-${deploymentPrefixLowercase}' +var avdSharedSResourcesScriptsContainerName = 'scripts-${deploymentPrefixLowercase}' +var avdSharedServicesKvName = 'avd-${uniqueString(deploymentPrefixLowercase, avdSharedServicesLocationLowercase, avdSharedServicesSubId)}-shared' // max length limit 24 characters + +// =========== // +// Deployments // +// =========== // + +// Resource groups (AVD shared services subscription RG). +module avdSharedResourcesRg '../../carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep' = { + scope: subscription(avdSharedServicesSubId) + name: 'AVD-RG-Shared-Resources-${time}' + params: { + name: avdSharedResourcesRgName + location: avdSharedServicesLocation + } +} + +// RBAC Roles. +module azureImageBuilderRole '../../carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep' = if (createAibCustomRole) { + scope: subscription(avdSharedServicesSubId) + name: 'Azure-Image-Builder-Role-${time}' + params: { + subscriptionId: avdSharedServicesSubId + description: 'Azure Image Builder AVD' + roleName: 'AzureImageBuilder-AVD' + actions: [ + 'Microsoft.Authorization/*/read' + 'Microsoft.Compute/images/write' + 'Microsoft.Compute/images/read' + 'Microsoft.Compute/images/delete' + 'Microsoft.Compute/galleries/read' + 'Microsoft.Compute/galleries/images/read' + 'Microsoft.Compute/galleries/images/versions/read' + 'Microsoft.Compute/galleries/images/versions/write' + 'Microsoft.Storage/storageAccounts/blobServices/containers/read' + 'Microsoft.Storage/storageAccounts/blobServices/containers/write' + 'Microsoft.Storage/storageAccounts/blobServices/read' + 'Microsoft.ContainerInstance/containerGroups/read' + 'Microsoft.ContainerInstance/containerGroups/write' + 'Microsoft.ContainerInstance/containerGroups/start/action' + 'Microsoft.ManagedIdentity/userAssignedIdentities/*/read' + 'Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action' + 'Microsoft.Authorization/*/read' + 'Microsoft.Resources/deployments/*' + 'Microsoft.Resources/deploymentScripts/read' + 'Microsoft.Resources/deploymentScripts/write' + 'Microsoft.Resources/subscriptions/resourceGroups/read' + 'Microsoft.VirtualMachineImages/imageTemplates/run/action' + 'Microsoft.VirtualMachineImages/imageTemplates/read' + 'Microsoft.Network/virtualNetworks/read' + 'Microsoft.Network/virtualNetworks/subnets/join/action' + ] + assignableScopes: [ + '/subscriptions/${avdSharedServicesSubId}' + ] + } +} +// + +// Managed identities. +module imageBuilderManagedIdentity '../../carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = if (createAibManagedIdentity) { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'image-Builder-Managed-Identity-${time}' + params: { + name: aibManagedIdentityName + location: avdSharedServicesLocation + } + dependsOn: [ + avdSharedResourcesRg + ] +} + +module deployScriptManagedIdentity '../../carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'deployment-Script-Managed-Identity-${time}' + params: { + name: deployScriptManagedIdentityName + location: avdSharedServicesLocation + } + dependsOn: [ + avdSharedResourcesRg + ] +} + +// Introduce delay for User Managed Assigned Identity to propagate through the system. +module userManagedIdentityDelay '../../carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep' = if (createAibManagedIdentity) { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'AVD-userManagedIdentityDelay-${time}' + params: { + name: 'AVD-userManagedIdentityDelay-${time}' + location: avdSharedServicesLocation + azPowerShellVersion: '6.2' + cleanupPreference: 'Always' + timeout: 'PT10M' + scriptContent: useSharedImage || createAibManagedIdentity ? ''' + Write-Host "Start" + Get-Date + Start-Sleep -Seconds 60 + Write-Host "Stop" + Get-Date + ''' : '' + } + dependsOn: [ + //imageBuilderManagedIdentity + deployScriptManagedIdentity + ] +} + +// Enterprise applications. +// RBAC role Assignments. +resource azureImageBuilderExistingRole 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = if (!createAibCustomRole) { + name: 'AzureImageBuilder-AVD' + scope: subscription(avdSharedServicesSubId) + } + +module azureImageBuilderRoleAssign '../../carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = { + name: 'Azure-Image-Builder-RoleAssign-${time}' + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + params: { + roleDefinitionIdOrName: createAibCustomRole ? azureImageBuilderRole.outputs.resourceId : azureImageBuilderExistingRole.id + principalId: createAibManagedIdentity ? imageBuilderManagedIdentity.outputs.principalId : existingAibManagedIdentityId + } + dependsOn: [ + userManagedIdentityDelay + ] +} + +module deployScriptRoleAssign '../../carml/1.2.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = { + name: 'deploy-script-RoleAssign-${time}' + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + params: { + roleDefinitionIdOrName: createAibCustomRole ? azureImageBuilderRole.outputs.resourceId : '/subscriptions/${avdSharedServicesSubId}/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + principalId: useSharedImage ? deployScriptManagedIdentity.outputs.principalId : '' + } + dependsOn: [ + userManagedIdentityDelay + ] +} + +// Custom images: Azure Image Builder deployment. Azure Compute Gallery --> Image Template Definition --> Image Template --> Build and Publish Template --> Create VMs. +// Azure Compute Gallery. +module azureComputeGallery '../../carml/1.2.0/Microsoft.Compute/galleries/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'Deploy-Azure-Compute-Gallery-${time}' + params: { + name: imageGalleryName + location: avdSharedServicesLocation + galleryDescription: 'Azure Virtual Desktops Images' + } + dependsOn: [ + avdSharedResourcesRg + ] +} + +// Image Template Definition. +module avdImageTemplataDefinition '../../carml/1.2.0/Microsoft.Compute/galleries/images/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'Deploy-AVD-Image-Template-Definition-${time}' + params: { + galleryName: useSharedImage ? azureComputeGallery.outputs.name : '' + name: imageDefinitionsTemSpecName + osState: avdOsImageDefinitions[avdOsImage].osState + osType: avdOsImageDefinitions[avdOsImage].osType + publisher: avdOsImageDefinitions[avdOsImage].publisher + offer: avdOsImageDefinitions[avdOsImage].offer + sku: avdOsImageDefinitions[avdOsImage].sku + location: aibLocation + hyperVGeneration: avdOsImageDefinitions[avdOsImage].hyperVGeneration + } + dependsOn: [ + azureComputeGallery + avdSharedResourcesRg + ] +} +// + +// Create Image Template. +module imageTemplate '../../carml/1.2.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'AVD-Deploy-Image-Template-${time}' + params: { + name: imageDefinitionsTemSpecName + userMsiName: createAibManagedIdentity && useSharedImage ? imageBuilderManagedIdentity.outputs.name : existingAibManagedIdentityName + userMsiResourceGroup: createAibManagedIdentity && useSharedImage ? imageBuilderManagedIdentity.outputs.resourceGroupName : avdSharedResourcesRgName + location: aibLocation + imageReplicationRegions: (avdSharedServicesLocation == aibLocation) ? array('${avdSharedServicesLocation}') : concat(array('${aibLocation}'), array('${avdSharedServicesLocation}')) + sigImageDefinitionId: useSharedImage ? avdImageTemplataDefinition.outputs.resourceId : '' + vmSize: imageVmSize + customizationSteps: [ + { + type: 'PowerShell' + name: 'OptimizeOS' + runElevated: true + runAsSystem: true + scriptUri: '${baseScriptUri}scripts/Optimize_OS_for_AVD.ps1' // need to update value to accelerator github after + } + + { + type: 'WindowsRestart' + restartCheckCommand: 'write-host "restarting post Optimizations"' + restartTimeout: '10m' + } + + { + type: 'WindowsUpdate' + searchCriteria: 'IsInstalled=0' + filters: [ + 'exclude:$_.Title -like \'*Preview*\'' + 'include:$true' + ] + updateLimit: 40 + } + { + type: 'PowerShell' + name: 'Sleep for a min' + runElevated: true + runAsSystem: true + inline: [ + 'Write-Host "Sleep for a 5 min" ' + 'Start-Sleep -Seconds 300' + ] + } + { + type: 'WindowsRestart' + restartCheckCommand: 'write-host "restarting post Windows updates"' + restartTimeout: '10m' + } + { + type: 'PowerShell' + name: 'Sleep for a min' + runElevated: true + runAsSystem: true + inline: [ + 'Write-Host "Sleep for a min" ' + 'Start-Sleep -Seconds 60' + ] + } + { + type: 'WindowsRestart' + restartTimeout: '10m' + } + ] + imageSource: { + type: 'PlatformImage' + publisher: avdOsImageDefinitions[avdOsImage].publisher + offer: avdOsImageDefinitions[avdOsImage].offer + sku: avdOsImageDefinitions[avdOsImage].sku + osAccountType: avdOsImageDefinitions[avdOsImage].osAccountType + version: 'latest' + } + } + dependsOn: [ + avdImageTemplataDefinition + azureComputeGallery + avdSharedResourcesRg + azureImageBuilderRoleAssign + ] +} + +// Build Image Template. +module imageTemplateBuild '../../carml/1.2.0/Microsoft.Resources/deploymentScripts/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'AVD-Build-Image-Template-${time}' + params: { + name: 'imageTemplateBuildName-${avdOsImage}' + location: aibLocation + azPowerShellVersion: '6.2' + cleanupPreference: 'Always' + timeout: 'PT2H' + containerGroupName: 'imageTemplateBuildName-${avdOsImage}-aci' + userAssignedIdentities: createAibManagedIdentity ? { + '${imageBuilderManagedIdentity.outputs.resourceId}': {} + } : { + '${existingAibManagedIdentityId}': {} + } + arguments: '-subscriptionId \'${avdSharedServicesSubId}\' -resourceGroupName \'${avdSharedResourcesRgName}\' -imageTemplateName \'${(useSharedImage ? imageTemplate.outputs.name : null)}\'' + scriptContent: useSharedImage ? ''' + param( + [string] [Parameter(Mandatory=$true)] $resourceGroupName, + [string] [Parameter(Mandatory=$true)] $imageTemplateName, + [string] [Parameter(Mandatory=$true)] $subscriptionId + ) + $ErrorActionPreference = "Stop" + Install-Module -Name Az.ImageBuilder -Force + # Kick off the Azure Image Build + Write-Host "Kick off Image buld for $imageTemplateName" + Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $resourceGroupName -ResourceType "Microsoft.VirtualMachineImages/imageTemplates" -Action Run -Force + $DeploymentScriptOutputs = @{} + $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName) + $status=$getStatus.LastRunStatusRunState + $statusMessage=$getStatus.LastRunStatusMessage + $startTime=Get-Date + $reset=$startTime + (New-TimeSpan -Minutes 40) + Write-Host "Script will time out in $reset" + do { + $now=Get-Date + Write-Host "Getting the current time: $now" + if (($now -eq $reset) -or ($now -gt $reset)) { + break + } + $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName) + $status=$getStatus.LastRunStatusRunState + Write-Host "Current status of the image build $imageTemplateName is: $status" + Write-Host "Script will time out in $reset" + $DeploymentScriptOutputs=$now + $DeploymentScriptOutputs=$status + if ($status -eq "Failed") { + Write-Host "Build failed for image template: $imageTemplateName. Check the Packer logs" + $DeploymentScriptOutputs="Build Failed" + throw "Build Failed" + } + if (($status -eq "Canceled") -or ($status -eq "Canceling") ) { + Write-Host "User canceled the build. Delete the Image template definition: $imageTemplateName" + throw "User canceled the build." + } + if ($status -eq "Succeeded") { + Write-Host "Success. Image template definition: $imageTemplateName is finished " + break + } + } + until (($now -eq $reset) -or ($now -gt $reset)) + Write-Host "Finished check for image build status at $now" + + + ''' : '' + } + dependsOn: [ + imageTemplate + avdSharedResourcesRg + azureImageBuilderRoleAssign + avdSharedServicesKeyVault + ] +} + +// Key vaults. +module avdSharedServicesKeyVault '../../carml/1.2.0/Microsoft.KeyVault/vaults/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'AVD-Shared-Services-KeyVault-${time}' + params: { + name: avdSharedServicesKvName + location: avdSharedServicesLocation + enableRbacAuthorization: false + enablePurgeProtection: true + softDeleteRetentionInDays: 7 + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + virtualNetworkRules: [] + ipRules: [] + } + } + dependsOn: [ + avdSharedResourcesRg + ] +} + +// Storage. +module avdSharedServicesStorage '../../carml/1.2.0/Microsoft.Storage/storageAccounts/deploy.bicep' = { + scope: resourceGroup('${avdSharedServicesSubId}', '${avdSharedResourcesRgName}') + name: 'AVD-Shared-Services-Storage-${time}' + params: { + name: avdSharedSResourcesStorageName + location: avdSharedServicesLocation + storageAccountSku: avdUseAvailabilityZones ? 'Standard_ZRS' : 'Standard_LRS' + storageAccountKind: 'StorageV2' + blobServices: { + containers: [ + { + name: avdSharedSResourcesAibContainerName + publicAccess: 'None' + } + { + name: avdSharedSResourcesScriptsContainerName + publicAccess: 'None' + } + ] + } + } + dependsOn: [ + avdSharedResourcesRg + ] +} diff --git a/workload/bicep/deploy.bicep b/workload/bicep/deploy.bicep new file mode 100644 index 000000000..765353803 --- /dev/null +++ b/workload/bicep/deploy.bicep @@ -0,0 +1,1286 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@minLength(2) +@maxLength(4) +@description('Required. The name of the resource group to deploy') +param deploymentPrefix string = '' + +@allowed([ + 'Multiple' + 'Single' +]) +@description('Required. AVD subscription model (Default: Multiple)') +param avdSubOrgsOption string = 'Multiple' + +@description('Required. Location where to deploy compute services') +param avdSessionHostLocation string = '' + +@description('Required. Location where to deploy AVD management plane') +param avdManagementPlaneLocation string = '' + +@description('Optional. AVD shared services subscription ID, single subscriptions scenario') +param avdSingleSubsId string = '' + +@description('Optional. AVD shared services subscription ID, multiple subscriptions scenario') +param avdShrdlSubsId string = '' + +@description('Optional. AVD workload subscription ID, multiple subscriptions scenario') +param avdWrklSubsId string = '' + +@description('Azure Virtual Desktop Enterprise Application object ID. ') +param avdEnterpriseAppObjectId string = '' + +@description('Required. AVD session host local credentials') +param avdVmLocalUserName string = '' +@secure() +param avdVmLocalUserPassword string = '' + +@description('Required. AD domain name') +param avdIdentityDomainName string = '' + +@description('Required. AVD session host domain join credentials') +param avdDomainJoinUserName string = '' +@secure() +param avdDomainJoinUserPassword string = '' + +@description('Optional. OU path to join AVd VMs') +param avdOuPath string = '' +/* +@description('Optional. Id to grant access to on AVD workload key vault secrets') +param avdWrklSecretAccess string = '' +*/ +@allowed([ + 'Personal' + 'Pooled' +]) +@description('Optional. AVD host pool type (Default: Pooled)') +param avdHostPoolType string = 'Pooled' + +@allowed([ + 'Automatic' + 'Direct' +]) +@description('Optional. AVD host pool type (Default: Automatic)') +param avdPersonalAssignType string = 'Automatic' + +@allowed([ + 'BreadthFirst' + 'DepthFirst' +]) +@description('Required. AVD host pool load balacing type (Default: BreadthFirst)') +param avdHostPoolloadBalancerType string = 'BreadthFirst' + +@description('Optional. AVD host pool maximum number of user sessions per session host') +param avhHostPoolMaxSessions int = 15 + +@description('Optional. AVD host pool start VM on Connect') +param avdStartVMOnConnect bool + +@description('Create custom Start VM on connect role') +param createStartVmOnConnectCustomRole bool + +@description('Optional. AVD deploy remote app application group') +param avdDeployRAppGroup bool + +@description('Optional. AVD host pool Custom RDP properties') +param avdHostPoolRdpProperty string = 'audiocapturemode:i:1;audiomode:i:0;drivestoredirect:s:;redirectclipboard:i:1;redirectcomports:i:1;redirectprinters:i:1;redirectsmartcards:i:1;screen mode id:i:2' + +@description('Create new virtual network') +param createAvdVnet bool + +/* +@description('Existing virtual network subscription') +param existingVnetSubscriptionId string = '' + +@description('Existing virtual network resource group') +param existingVnetRgName string = '' + +@description('Existing virtual network') +param existingVnetName string = '' + +@description('Existing virtual network subnet (subnet requires PrivateEndpointNetworkPolicies property to be disabled)') +param existingVnetSubnetName string = '' +*/ + +@description('Existing virtual network subnet') +param existingVnetSubnetResourceId string = '' + +/* +@description('Existing hub virtual network subscription') +param existingHubVnetSubscriptionId string + +@description('Existing hub virtual network resource group') +param existingHubVnetRgName string = '' + +@description('Existing hub virtual network') +param existingHubVnetName string = '' +*/ +@description('Existing hub virtual network for perring') +param existingHubVnetResourceId string = '' + +@description('AVD virtual network address prefixes') +param avdVnetworkAddressPrefixes string = '' + +@description('AVD virtual network subnet address prefix') +param avdVnetworkSubnetAddressPrefix string = '' + +@description('custom DNS servers IPs') +param customDnsIps string = '' + +@description('Does the hub contains a virtual network gateway') +param vNetworkGatewayOnHub bool + +@description('Optional. Fslogix file share size (Default: 5TB)') +param avdFslogixFileShareQuotaSize int = 512 + +@description('Deploy new session hosts') +param avdDeploySessionHosts bool + +@minValue(1) +@maxValue(500) +@description('Cuantity of session hosts to deploy') +param avdDeploySessionHostsCount int + +@description('Optional. Creates an availability zone and adds the VMs to it. Cannot be used in combination with availability set nor scale set. (Defualt: true)') +param avdUseAvailabilityZones bool = true + +@description('Storage account SKU for FSLogix storage. Recommended tier is Premium LRS or Premium ZRS (where available)') +param fsLogixstorageSku string = '' + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool = true + +@description('Session host VM size (Defualt: Standard_D2s_v4) ') +param avdSessionHostsSize string = 'Standard_D2s_v4' + +@description('OS disk type for session host (Defualt: Standard_LRS) ') +param avdSessionHostDiskType string = 'Standard_LRS' + +@allowed([ + 'eastus' + 'eastus2' + 'westcentralus' + 'westus' + 'westus2' + 'westus3' + 'southcentralus' + 'northeurope' + 'westeurope' + 'southeastasia' + 'australiasoutheast' + 'australiaeast' + 'uksouth' + 'ukwest' +]) +@description('Azure image builder location (Defualt: eastus2)') +param aiblocation string = 'eastus2' + +@description('Create custom azure image builder role') +param createAibCustomRole bool = true + +@allowed([ + 'win10_21h2_office' + 'win10_21h2' + 'win11_21h2_office' + 'win11_21h2' +]) +@description('Required. AVD OS image source (Default: win10-21h2)') +param avdOsImage string = 'win10_21h2' + +@description('Set to deploy image from Azure Compute Gallery') +param useSharedImage bool + +@description('Regions to replicate AVD images (Defualt: eastus2)') +param avdImageRegionsReplicas array = [ + 'eastus2' +] + +@description('Create azure image Builder managed identity') +param createAibManagedIdentity bool = true + +@description('Do not modify, used to set unique value for resource deployment') +param time string = utcNow() + +// =========== // +// Variable declaration // +// =========== // +var deploymentPrefixLowercase = toLower(deploymentPrefix) +var avdSessionHostLocationLowercase = toLower(avdSessionHostLocation) +var avdManagementPlaneLocationLowercase = toLower(avdManagementPlaneLocation) +var avdWrklSubscriptionId = (avdSubOrgsOption == 'Multiple') ? avdWrklSubsId : avdSingleSubsId +var avdShrdlSubscriptionId = (avdSubOrgsOption == 'Multiple') ? avdShrdlSubsId : avdSingleSubsId +var avdServiceObjectsRgName = 'rg-${avdManagementPlaneLocationLowercase}-avd-${deploymentPrefixLowercase}-service-objects' // max length limit 90 characters +var avdNetworkObjectsRgName = 'rg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}-network' // max length limit 90 characters +var avdComputeObjectsRgName = 'rg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}-pool-compute' // max length limit 90 characters +var avdStorageObjectsRgName = 'rg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}-storage' // max length limit 90 characters +var avdSharedResourcesRgName = 'rg-${avdSessionHostLocationLowercase}-avd-shared-resources' +var imageGalleryName = 'avdgallery${avdSessionHostLocationLowercase}' +//var existingVnetResourceId = '/subscriptions/${existingVnetSubscriptionId}/resourceGroups/${existingVnetRgName}/providers/Microsoft.Network/virtualNetworks/${existingVnetName}' +//var hubVnetId = '/subscriptions/${existingHubVnetSubscriptionId}/resourceGroups/${existingHubVnetRgName}/providers/Microsoft.Network/virtualNetworks/${existingHubVnetName}' +var avdVnetworkName = 'vnet-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}' +var avdVnetworkSubnetName = 'avd-${deploymentPrefixLowercase}' +var avdNetworksecurityGroupName = 'nsg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}' +var avdRouteTableName = 'udr-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}' +var avdApplicationsecurityGroupName = 'asg-${avdSessionHostLocationLowercase}-avd-${deploymentPrefixLowercase}' +var avdVNetworkPeeringName = '${uniqueString(deploymentPrefixLowercase, avdSessionHostLocation)}-peering-avd-${deploymentPrefixLowercase}' +var avdWorkSpaceName = 'avdws-${deploymentPrefixLowercase}' +var avdHostPoolName = 'avdhp-${deploymentPrefixLowercase}' +var avdApplicationGroupNameDesktop = 'avd-dag-${deploymentPrefixLowercase}' +var avdApplicationGroupNameRApp = 'avd-raag-${deploymentPrefixLowercase}' +var aibManagedIdentityName = 'avd-uai-aib' +var deployScriptManagedIdentityName = 'avd-uai-deployScript' +var imageDefinitionsTemSpecName = 'AVDImageDefinition_${avdOsImage}' +var imageVmSize = 'Standard_D4s_v3' +var avdOsImageDefinitions = { + 'win10_21h2_office': { + name: 'Windows10_21H2_Office' + osType: 'Windows' + osState: 'Generalized' + offer: 'office-365' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win10-21h2-avd-m365' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V1' + } + 'win10_21h2': { + name: 'Windows10_21H2' + osType: 'Windows' + osState: 'Generalized' + offer: 'windows-10' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win10-21h2-avd' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V1' + } + 'win11_21h2_office': { + name: 'Windows11_21H2' + osType: 'Windows' + osState: 'Generalized' + offer: 'office-365' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win11-21h2-avd-m365' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V2' + } + 'win11_21h2': { + name: 'Windows11_21H2' + osType: 'Windows' + osState: 'Generalized' + offer: 'windows-11' + publisher: 'MicrosoftWindowsDesktop' + sku: 'win11-21h2-avd' + osAccountType: 'Standard_LRS' + hyperVGeneration: 'V2' + } +} + +var marketPlaceGalleryWindows = { + 'win10_21h2_office': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'office-365' + sku: 'win10-21h2-avd-m365' + version: 'latest' + } + + 'win10_21h2': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'windows-10' + sku: 'win10-21h2-avd' + version: 'latest' + } + + 'win11_21h2_office': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'office-365' + sku: 'win11-21h2-avd-m365' + version: 'latest' + } + + 'win11_21h2': { + publisher: 'MicrosoftWindowsDesktop' + offer: 'Windows-11' + sku: 'win11-21h2-avd' + version: 'latest' + } +} + +var baseScriptUri = 'https://raw.githubusercontent.com/nataliakon/ResourceModules/AVD-Accelerator/workload/' +var fslogixScriptUri = '${baseScriptUri}Scripts/Set-FSLogixRegKeys.ps1' +var fsLogixScript = './Set-FSLogixRegKeys.ps1' +var fslogixSharePath = '\\\\${avdFslogixStorageName}.file.${environment().suffixes.storage}\\${avdFslogixFileShareName}' +var FsLogixScriptArguments = '-volumeshare ${fslogixSharePath}' +// var avdAgentPackageLocation = 'https://wvdportalstorageblob.blob.${environment().suffixes.storage}/galleryartifacts/Configuration_01-20-2022.zip' +var avdAgentPackageLocation = 'https://wvdportalstorageblob.blob.${environment().suffixes.storage}/galleryartifacts/Configuration_10-6-2021.zip' +var avdFslogixStorageName = 'fslogix${uniqueString(deploymentPrefixLowercase, avdSessionHostLocationLowercase)}${deploymentPrefixLowercase}' +var avdFslogixFileShareName = 'fslogix-${deploymentPrefixLowercase}' +var avdSharedSResourcesStorageName = 'avd${uniqueString(deploymentPrefixLowercase, avdSessionHostLocationLowercase)}shared' +var avdSharedSResourcesAibContainerName = 'aib-${deploymentPrefixLowercase}' +var avdSharedSResourcesScriptsContainerName = 'scripts-${deploymentPrefixLowercase}' +var avdSharedServicesKvName = 'avd-${uniqueString(deploymentPrefixLowercase, avdSessionHostLocationLowercase)}-shared' // max length limit 24 characters +var avdWrklKvName = 'avd-${uniqueString(deploymentPrefixLowercase, avdSessionHostLocationLowercase)}-${deploymentPrefixLowercase}' // max length limit 24 characters +var avdSessionHostNamePrefix = 'avdsh-${deploymentPrefix}' +var avdAvailabilitySetName = 'avdas-${deploymentPrefix}' +var allAvailabilityZones = pickZones('Microsoft.Compute', 'virtualMachines', avdSessionHostLocation, 3) + +// =========== // +// Deployments // +// =========== // + +// Resource groups +// AVD shared services subscription RGs +module avdSharedResourcesRg '../carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep' = { + scope: subscription(avdShrdlSubscriptionId) + name: 'AVD-RG-Shared-Resources-${time}' + params: { + name: avdSharedResourcesRgName + location: avdSessionHostLocation + } +} +// AVD Workload subscription RGs +module avdServiceObjectsRg '../carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep' = { + scope: subscription(avdWrklSubscriptionId) + name: 'AVD-RG-ServiceObjects-${time}' + params: { + name: avdServiceObjectsRgName + location: avdManagementPlaneLocation + } +} + +module avdNetworkObjectsRg '../carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep' = if (createAvdVnet) { + scope: subscription(avdWrklSubscriptionId) + name: 'AVD-RG-Network-${time}' + params: { + name: avdNetworkObjectsRgName + location: avdSessionHostLocation + } +} + +module avdComputeObjectsRg '../carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep' = { + scope: subscription(avdWrklSubscriptionId) + name: 'AVD-RG-Compute-${time}' + params: { + name: avdComputeObjectsRgName + location: avdSessionHostLocation + } +} + +module avdStorageObjectsRg '../carml/1.0.0/Microsoft.Resources/resourceGroups/deploy.bicep' = { + scope: subscription(avdWrklSubscriptionId) + name: 'AVD-RG-Storage-${time}' + params: { + name: avdStorageObjectsRgName + location: avdSessionHostLocation + } +} +// + +// Networking +module avdNetworksecurityGroup '../carml/1.0.0/Microsoft.Network/networkSecurityGroups/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdNetworkObjectsRgName}') + name: 'AVD-NSG-${time}' + params: { + name: avdNetworksecurityGroupName + location: avdSessionHostLocation + } + dependsOn: [ + avdNetworkObjectsRg + ] +} + +module avdApplicationSecurityGroup '../carml/1.0.0/Microsoft.Network/applicationSecurityGroups/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdComputeObjectsRgName}') + name: 'AVD-ASG-${time}' + params: { + name: avdApplicationsecurityGroupName + location: avdSessionHostLocation + } + dependsOn: [ + avdComputeObjectsRg + ] +} + +module avdRouteTable '../carml/1.0.0/Microsoft.Network/routeTables/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdNetworkObjectsRgName}') + name: 'AVD-UDR-${time}' + params: { + name: avdRouteTableName + location: avdSessionHostLocation + } + dependsOn: [ + avdNetworkObjectsRg + ] +} + +module avdVirtualNetwork '../carml/1.0.0/Microsoft.Network/virtualNetworks/deploy.bicep' = if (createAvdVnet) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdNetworkObjectsRgName}') + name: 'AVD-vNet-${time}' + params: { + name: avdVnetworkName + location: avdSessionHostLocation + addressPrefixes: array(avdVnetworkAddressPrefixes) + dnsServers: !empty(customDnsIps) ? array(customDnsIps) : [] + virtualNetworkPeerings: [ + { + remoteVirtualNetworkId: existingHubVnetResourceId + name: avdVNetworkPeeringName + allowForwardedTraffic: true + allowGatewayTransit: false + allowVirtualNetworkAccess: true + doNotVerifyRemoteGateways: true + useRemoteGateways: vNetworkGatewayOnHub ? true : false + remotePeeringEnabled: true + remotePeeringName: avdVNetworkPeeringName + remotePeeringAllowForwardedTraffic: true + remotePeeringAllowGatewayTransit: vNetworkGatewayOnHub ? true : false + remotePeeringAllowVirtualNetworkAccess: true + remotePeeringDoNotVerifyRemoteGateways: true + remotePeeringUseRemoteGateways: false + } + ] + subnets: [ + { + name: avdVnetworkSubnetName + addressPrefix: avdVnetworkSubnetAddressPrefix + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Enabled' + networkSecurityGroupName: avdNetworksecurityGroupName + routeTableName: avdRouteTableName + } + ] + } + dependsOn: [ + avdNetworkObjectsRg + avdNetworksecurityGroup + avdApplicationSecurityGroup + avdRouteTable + ] +} + +// + +// AVD management plane +module avdWorkSpace '../carml/1.0.0/Microsoft.DesktopVirtualization/workspaces/deploy.bicep' = { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') + name: 'AVD-WorkSpace-${time}' + params: { + name: avdWorkSpaceName + location: avdManagementPlaneLocation + appGroupResourceIds: [ + avdApplicationGroupDesktop.outputs.resourceId + avdDeployRAppGroup ? avdApplicationGroupRApp.outputs.resourceId : '' + ] + } + dependsOn: [ + avdServiceObjectsRg + avdApplicationGroupDesktop + avdApplicationGroupRApp + ] +} + +module avdHostPool '../carml/1.0.0/Microsoft.DesktopVirtualization/hostpools/deploy.bicep' = { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') + name: 'AVD-HostPool-${time}' + params: { + name: avdHostPoolName + location: avdManagementPlaneLocation + hostpoolType: avdHostPoolType + startVMOnConnect: avdStartVMOnConnect + customRdpProperty: avdHostPoolRdpProperty + loadBalancerType: avdHostPoolloadBalancerType + maxSessionLimit: avhHostPoolMaxSessions + personalDesktopAssignmentType: avdPersonalAssignType + } + dependsOn: [ + avdServiceObjectsRg + ] +} + +module avdApplicationGroupDesktop '../carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep' = { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') + name: 'AVD-AppGroup-Desktop-${time}' + params: { + name: avdApplicationGroupNameDesktop + location: avdManagementPlaneLocation + applicationGroupType: 'Desktop' + hostpoolName: avdHostPool.outputs.name + } + dependsOn: [ + avdServiceObjectsRg + avdHostPool + ] +} + +module avdApplicationGroupRApp '../carml/1.0.0/Microsoft.DesktopVirtualization/applicationgroups/deploy.bicep' = if (avdDeployRAppGroup) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') + name: 'AVD-AppGroup-RApp-${time}' + params: { + name: avdApplicationGroupNameRApp + location: avdManagementPlaneLocation + applicationGroupType: 'RemoteApp' + hostpoolName: avdHostPool.outputs.name + } + dependsOn: [ + avdServiceObjectsRg + avdHostPool + ] +} +// + +// RBAC Roles +module startVMonConnectRole '../carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep' = if (createStartVmOnConnectCustomRole) { + scope: subscription(avdWrklSubscriptionId) + name: 'Start-VM-on-Connect-Role-${time}' + params: { + subscriptionId: avdWrklSubscriptionId + description: 'Start VM on connect AVD' + roleName: 'StartVMonConnect-AVD' + actions: [ + 'Microsoft.Compute/virtualMachines/start/action' + 'Microsoft.Compute/virtualMachines/*/read' + ] + assignableScopes: [ + '/subscriptions/${avdWrklSubscriptionId}' + ] + } +} + +module azureImageBuilderRole '../carml/1.0.0/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep' = if (createAibCustomRole) { + scope: subscription(avdShrdlSubscriptionId) + name: 'Azure-Image-Builder-Role-${time}' + params: { + subscriptionId: avdShrdlSubscriptionId + description: 'Azure Image Builder AVD' + roleName: 'AzureImageBuilder-AVD' + actions: [ + 'Microsoft.Authorization/*/read' + 'Microsoft.Compute/images/write' + 'Microsoft.Compute/images/read' + 'Microsoft.Compute/images/delete' + 'Microsoft.Compute/galleries/read' + 'Microsoft.Compute/galleries/images/read' + 'Microsoft.Compute/galleries/images/versions/read' + 'Microsoft.Compute/galleries/images/versions/write' + 'Microsoft.Storage/storageAccounts/blobServices/containers/read' + 'Microsoft.Storage/storageAccounts/blobServices/containers/write' + 'Microsoft.Storage/storageAccounts/blobServices/read' + 'Microsoft.ContainerInstance/containerGroups/read' + 'Microsoft.ContainerInstance/containerGroups/write' + 'Microsoft.ContainerInstance/containerGroups/start/action' + 'Microsoft.ManagedIdentity/userAssignedIdentities/*/read' + 'Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action' + 'Microsoft.Authorization/*/read' + 'Microsoft.Resources/deployments/*' + 'Microsoft.Resources/deploymentScripts/read' + 'Microsoft.Resources/deploymentScripts/write' + 'Microsoft.Resources/subscriptions/resourceGroups/read' + 'Microsoft.VirtualMachineImages/imageTemplates/run/action' + 'Microsoft.VirtualMachineImages/imageTemplates/read' + 'Microsoft.Network/virtualNetworks/read' + 'Microsoft.Network/virtualNetworks/subnets/join/action' + ] + assignableScopes: [ + '/subscriptions/${avdShrdlSubscriptionId}' + ] + } +} +// + +// Managed identities +module imageBuilderManagedIdentity '../carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = if (createAibManagedIdentity) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'image-Builder-Managed-Identity-${time}' + params: { + name: aibManagedIdentityName + location: avdSessionHostLocation + } + dependsOn: [ + avdSharedResourcesRg + ] +} + +module deployScriptManagedIdentity '../carml/1.0.0/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = if (useSharedImage) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'deployment-Script-Managed-Identity-${time}' + params: { + name: deployScriptManagedIdentityName + location: avdSessionHostLocation + } + dependsOn: [ + avdSharedResourcesRg + ] +} +// + +// Introduce delay for User Managed Assigned Identity to propagate through the system + +module userManagedIdentityDelay '../carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep' = if (useSharedImage || createAibManagedIdentity) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'AVD-userManagedIdentityDelay-${time}' + params: { + name: 'AVD-userManagedIdentityDelay-${time}' + location: avdSessionHostLocation + azPowerShellVersion: '6.2' + cleanupPreference: 'Always' + timeout: 'PT10M' + scriptContent: useSharedImage || createAibManagedIdentity ? ''' + Write-Host "Start" + Get-Date + Start-Sleep -Seconds 60 + Write-Host "Stop" + Get-Date + ''' : '' + } + dependsOn: [ + imageBuilderManagedIdentity + deployScriptManagedIdentity + ] +} + +// Enterprise applications +// + +// RBAC role Assignments +module azureImageBuilderRoleAssign '../carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = if (createAibCustomRole && createAibManagedIdentity) { + name: 'Azure-Image-Builder-RoleAssign-${time}' + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + params: { + roleDefinitionIdOrName: createAibCustomRole ? azureImageBuilderRole.outputs.resourceId : '' + principalId: createAibManagedIdentity ? imageBuilderManagedIdentity.outputs.principalId : '' + } + dependsOn: [ + userManagedIdentityDelay + ] +} + +module deployScriptRoleAssign '../carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = if (createAibCustomRole && useSharedImage) { + name: 'deploy-script-RoleAssign-${time}' + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + params: { + roleDefinitionIdOrName: createAibCustomRole ? azureImageBuilderRole.outputs.resourceId : '/subscriptions/${avdShrdlSubscriptionId}/providers/Microsoft.Authorization/roleDefinitions/f1a07417-d97a-45cb-824c-7a7467783830' + principalId: useSharedImage ? deployScriptManagedIdentity.outputs.principalId : '' + } + dependsOn: [ + userManagedIdentityDelay + ] +} + +/* +module azureImageBuilderRoleAssignExisting '../arm/1.0.0/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_rg.bicep' = if (!createAibCustomRole && createAibManagedIdentity) { + name: 'Azure-Image-Builder-RoleAssign-${time}' + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + params: { + roleDefinitionIdOrName: createAibCustomRole ? azureImageBuilderRole.outputs.resourceId : '' + principalId: imageBuilderManagedIdentity.outputs.principalId + } + dependsOn: [ + azureImageBuilderRole + imageBuilderManagedIdentity + ] +} +*/ +module startVMonConnectRoleAssign '../carml/1.0.0/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep' = if (createStartVmOnConnectCustomRole) { + name: 'Start-VM-OnConnect-RoleAssign-${time}' + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdComputeObjectsRgName}') + params: { + roleDefinitionIdOrName: createStartVmOnConnectCustomRole ? startVMonConnectRole.outputs.resourceId : '' + principalId: avdEnterpriseAppObjectId + } + dependsOn: [ + avdServiceObjectsRg + startVMonConnectRole + ] +} + +// Custom images: Azure Image Builder deployment. Azure Compute Gallery --> Image Template Definition --> Image Template --> Build and Publish Template --> Create VMs +// Azure Compute Gallery +module azureComputeGallery '../carml/1.0.0/Microsoft.Compute/galleries/deploy.bicep' = if (useSharedImage) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'Deploy-Azure-Compute-Gallery-${time}' + params: { + name: imageGalleryName + location: avdSessionHostLocation + + galleryDescription: 'Azure Virtual Desktops Images' + } + dependsOn: [ + avdSharedResourcesRg + ] +} +// + +// Image Template Definition +module avdImageTemplataDefinition '../carml/1.0.0/Microsoft.Compute/galleries/images/deploy.bicep' = if (useSharedImage) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'Deploy-AVD-Image-Template-Definition-${time}' + params: { + galleryName: useSharedImage ? azureComputeGallery.outputs.name : '' + name: imageDefinitionsTemSpecName + osState: avdOsImageDefinitions[avdOsImage].osState + osType: avdOsImageDefinitions[avdOsImage].osType + publisher: avdOsImageDefinitions[avdOsImage].publisher + offer: avdOsImageDefinitions[avdOsImage].offer + sku: avdOsImageDefinitions[avdOsImage].sku + location: aiblocation + hyperVGeneration: avdOsImageDefinitions[avdOsImage].hyperVGeneration + } + dependsOn: [ + azureComputeGallery + avdSharedResourcesRg + ] +} + +// + +// Create Image Template +module imageTemplate '../carml/1.0.0/Microsoft.VirtualMachineImages/imageTemplates/deploy.bicep' = if (useSharedImage) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'AVD-Deploy-Image-Template-${time}' + params: { + name: imageDefinitionsTemSpecName + userMsiName: createAibManagedIdentity && useSharedImage ? imageBuilderManagedIdentity.outputs.name : '' + userMsiResourceGroup: createAibManagedIdentity && useSharedImage ? imageBuilderManagedIdentity.outputs.resourceGroupName : '' + location: aiblocation + imageReplicationRegions: (avdSessionHostLocation == aiblocation) ? array('${avdSessionHostLocation}') : concat(array('${aiblocation}'), array('${avdSessionHostLocation}')) + sigImageDefinitionId: useSharedImage ? avdImageTemplataDefinition.outputs.resourceId : '' + vmSize: imageVmSize + customizationSteps: [ + { + type: 'PowerShell' + name: 'OptimizeOS' + runElevated: true + runAsSystem: true + scriptUri: '${baseScriptUri}Scripts/Optimize_OS_for_AVD.ps1' // need to update value to accelerator github after + } + + { + type: 'WindowsRestart' + restartCheckCommand: 'write-host "restarting post Optimizations"' + restartTimeout: '10m' + } + + { + type: 'WindowsUpdate' + searchCriteria: 'IsInstalled=0' + filters: [ + 'exclude:$_.Title -like \'*Preview*\'' + 'include:$true' + ] + updateLimit: 40 + } + { + type: 'PowerShell' + name: 'Sleep for a min' + runElevated: true + runAsSystem: true + inline: [ + 'Write-Host "Sleep for a 5 min" ' + 'Start-Sleep -Seconds 300' + ] + } + { + type: 'WindowsRestart' + restartCheckCommand: 'write-host "restarting post Windows updates"' + restartTimeout: '10m' + } + { + type: 'PowerShell' + name: 'Sleep for a min' + runElevated: true + runAsSystem: true + inline: [ + 'Write-Host "Sleep for a min" ' + 'Start-Sleep -Seconds 60' + ] + } + { + type: 'WindowsRestart' + restartTimeout: '10m' + } + ] + imageSource: { + type: 'PlatformImage' + publisher: avdOsImageDefinitions[avdOsImage].publisher + offer: avdOsImageDefinitions[avdOsImage].offer + sku: avdOsImageDefinitions[avdOsImage].sku + osAccountType: avdOsImageDefinitions[avdOsImage].osAccountType + version: 'latest' + } + } + dependsOn: [ + avdImageTemplataDefinition + azureComputeGallery + avdSharedResourcesRg + azureImageBuilderRoleAssign + ] +} +// + +// Build Image Template +module imageTemplateBuild '../carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep' = if (useSharedImage) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'AVD-Build-Image-Template-${time}' + params: { + name: 'imageTemplateBuildName-${avdOsImage}' + location: aiblocation + azPowerShellVersion: '6.2' + cleanupPreference: 'Always' + timeout: 'PT2H' + containerGroupName: 'imageTemplateBuildName-${avdOsImage}-aci' + userAssignedIdentities: createAibManagedIdentity ? { + '${imageBuilderManagedIdentity.outputs.resourceId}': {} + } : {} + arguments: '-subscriptionId \'${avdShrdlSubscriptionId}\' -resourceGroupName \'${avdSharedResourcesRgName}\' -imageTemplateName \'${(useSharedImage ? imageTemplate.outputs.name : null)}\'' + scriptContent: useSharedImage ? ''' + param( + [string] [Parameter(Mandatory=$true)] $resourceGroupName, + [string] [Parameter(Mandatory=$true)] $imageTemplateName, + [string] [Parameter(Mandatory=$true)] $subscriptionId + ) + $ErrorActionPreference = "Stop" + Install-Module -Name Az.ImageBuilder -Force + # Kick off the Azure Image Build + Write-Host "Kick off Image buld for $imageTemplateName" + Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $resourceGroupName -ResourceType "Microsoft.VirtualMachineImages/imageTemplates" -Action Run -Force + $DeploymentScriptOutputs = @{} + $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName) + $status=$getStatus.LastRunStatusRunState + $statusMessage=$getStatus.LastRunStatusMessage + $startTime=Get-Date + $reset=$startTime + (New-TimeSpan -Minutes 40) + Write-Host "Script will time out in $reset" + do { + $now=Get-Date + Write-Host "Getting the current time: $now" + if (($now -eq $reset) -or ($now -gt $reset)) { + break + } + $expiryTime=(Get-AzAccessToken).ExpiresOn.Datetime + Write-Host "Token expiry time is $expiryTime" + $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName) + $status=$getStatus.LastRunStatusRunState + Write-Host "Current status of the image build $imageTemplateName is: $status" + Write-Host "Script will time out in $reset" + $DeploymentScriptOutputs=$now + $DeploymentScriptOutputs=$status + if ($status -eq "Failed") { + Write-Host "Build failed for image template: $imageTemplateName. Check the Packer logs" + $DeploymentScriptOutputs="Build Failed" + throw "Build Failed" + } + if (($status -eq "Canceled") -or ($status -eq "Canceling") ) { + Write-Host "User canceled the build. Delete the Image template definition: $imageTemplateName" + throw "User canceled the build." + } + if ($status -eq "Succeeded") { + Write-Host "Success. Image template definition: $imageTemplateName is finished " + break + } + } + until (($now -eq $reset) -or ($now -gt $reset)) + Write-Host "Finished check for image build status at $now" + + + ''' : '' + } + dependsOn: [ + imageTemplate + avdSharedResourcesRg + azureImageBuilderRoleAssign + ] +} + +// Execute Deployment script to check the status of the image build. + +module imageTemplateBuildCheck '../carml/1.0.0/Microsoft.Resources/deploymentScripts/deploy.bicep' = if (useSharedImage) { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'AVD-Build-Image-Template-${avdOsImage}-Check-Build' + params: { + name: 'imageTemplateBuildCheckName-${avdOsImage}' + location: aiblocation + timeout: 'PT30M' + containerGroupName: 'imageTemplateBuildCheckName-${avdOsImage}-aci' + runOnce: false + azPowerShellVersion: '6.2' + cleanupPreference: 'Always' + userAssignedIdentities: useSharedImage ? { + '${deployScriptManagedIdentity.outputs.resourceId}': {} + } : {} + arguments: '-subscriptionId \'${avdShrdlSubscriptionId}\' -resourceGroupName \'${avdSharedResourcesRgName}\' -imageTemplateName \'${(useSharedImage ? imageTemplate.outputs.name : null)}\'' + scriptContent: useSharedImage ? ''' + param( + [string] [Parameter(Mandatory=$true)] $resourceGroupName, + [string] [Parameter(Mandatory=$true)] $imageTemplateName, + [string] [Parameter(Mandatory=$true)] $subscriptionId + ) + $ErrorActionPreference = "Stop" + Install-Module -Name Az.ImageBuilder -Force + $DeploymentScriptOutputs = @{} + $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName) + $status=$getStatus.LastRunStatusRunState + $statusMessage=$getStatus.LastRunStatusMessage + $startTime=Get-Date + $reset=$startTime + (New-TimeSpan -Minutes 40) + Write-Host "Script will time out in $reset" + do { + $now=Get-Date + Write-Host "Getting the current time: $now" + if (($now -eq $reset) -or ($now -gt $reset)) { + break + } + $expiryTime=(Get-AzAccessToken).ExpiresOn.Datetime + Write-Host "Token expiry time is $expiryTime" + $getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName) + $status=$getStatus.LastRunStatusRunState + Write-Host "Current status of the image build $imageTemplateName is: $status" + Write-Host "Script will time out in $reset" + $DeploymentScriptOutputs=$now + $DeploymentScriptOutputs=$status + if ($status -eq "Failed") { + Write-Host "Build failed for image template: $imageTemplateName. Check the Packer logs" + $DeploymentScriptOutputs="Build Failed" + throw "Build Failed" + } + if (($status -eq "Canceled") -or ($status -eq "Canceling") ) { + Write-Host "User canceled the build. Delete the Image template definition: $imageTemplateName" + throw "User canceled the build." + } + if ($status -eq "Succeeded") { + Write-Host "Success. Image template definition: $imageTemplateName is finished " + break + } + } + until (($now -eq $reset) -or ($now -gt $reset)) + Write-Host "Finished check for image build status at $now" + + ''' : '' + } + dependsOn: [ + imageTemplate //we need to make this dependson conditional so it plays well with other deployment flags + avdSharedResourcesRg + azureImageBuilderRoleAssign + imageTemplateBuild //we need to make this dependson conditional so it plays well with other deployment flags + ] +} + +// + +// Key vaults +module avdWrklKeyVault '../carml/1.0.0/Microsoft.KeyVault/vaults/deploy.bicep' = { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') + name: 'AVD-Workload-KeyVault-${time}' + params: { + name: avdWrklKvName + location: avdSessionHostLocation + enableRbacAuthorization: false + softDeleteRetentionInDays: 7 + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + virtualNetworkRules: [] + ipRules: [] + } + privateEndpoints: [ + { + //subnetResourceId: createAvdVnet ? '${avdVirtualNetwork.outputs.resourceId}/subnets/${avdVnetworkSubnetName}' : '${existingVnetResourceId}/subnets/${existingVnetSubnetName}' + subnetResourceId: createAvdVnet ? '${avdVirtualNetwork.outputs.resourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + service: 'vault' + } + ] + secrets: { + secureList: [ + { + name: 'avdVmLocalUserPassword' + value: avdVmLocalUserPassword + contentType: 'Session host local user credentials' + } + { + name: 'avdVmLocalUserName' + value: avdVmLocalUserName + contentType: 'Session host local user credentials' + } + { + name: 'avdDomainJoinUserName' + value: avdDomainJoinUserName + contentType: 'Domain join credentials' + } + { + name: 'avdDomainJoinUserPassword' + value: avdDomainJoinUserPassword + contentType: 'Domain join credentials' + } + ] + } + /* + accessPolicies: [ + { + objectId: avdWrklSecretAccess + permissions: { + secrets: [ + 'get' + 'list' + ] + } + } + ] + */ + } + dependsOn: [ + avdComputeObjectsRg + ] +} + +module avdSharedServicesKeyVault '../carml/1.0.0/Microsoft.KeyVault/vaults/deploy.bicep' = { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'AVD-Shared-Services-KeyVault-${time}' + params: { + name: avdSharedServicesKvName + location: avdSessionHostLocation + enableRbacAuthorization: false + softDeleteRetentionInDays: 7 + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + virtualNetworkRules: [] + ipRules: [] + } + } + dependsOn: [ + avdSharedResourcesRg + ] +} +// + +// Storage + +module fslogixStorage '../carml/1.0.0/Microsoft.Storage/storageAccounts/deploy.bicep' = if (avdDeploySessionHosts) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdStorageObjectsRgName}') + name: 'AVD-Fslogix-Storage-${time}' + params: { + name: avdFslogixStorageName + location: avdSessionHostLocation + storageAccountSku: fsLogixstorageSku + allowBlobPublicAccess: false + //azureFilesIdentityBasedAuthentication: + storageAccountKind: ((fsLogixstorageSku =~ 'Premium_LRS') || (fsLogixstorageSku =~ 'Premium_ZRS')) ? 'FileStorage': 'StorageV2' + storageAccountAccessTier: 'Hot' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + virtualNetworkRules: [] + ipRules: [] + } + fileServices: { + shares: [ + { + name: avdFslogixFileShareName + shareQuota: avdFslogixFileShareQuotaSize * 100 //Portal UI steps scale + } + ] + } + privateEndpoints: [ + { + //subnetResourceId: createAvdVnet ? '${avdVirtualNetwork.outputs.resourceId}/subnets/${avdVnetworkSubnetName}' : '${existingVnetResourceId}/subnets/${existingVnetSubnetName}' + subnetResourceId: createAvdVnet ? '${avdVirtualNetwork.outputs.resourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + service: 'file' + } + ] + } + dependsOn: [ + avdStorageObjectsRg + ] +} + +module avdSharedServicesStorage '../carml/1.0.0/Microsoft.Storage/storageAccounts/deploy.bicep' = { + scope: resourceGroup('${avdShrdlSubscriptionId}', '${avdSharedResourcesRgName}') + name: 'AVD-Shared-Services-Storage-${time}' + params: { + name: avdSharedSResourcesStorageName + location: avdSessionHostLocation + storageAccountSku: avdUseAvailabilityZones ? 'Standard_ZRS' : 'Standard_LRS' + storageAccountKind: 'StorageV2' + blobServices: { + containers: [ + { + name: avdSharedSResourcesAibContainerName + publicAccess: 'None' + } + { + name: avdSharedSResourcesScriptsContainerName + publicAccess: 'None' + } + ] + } + } + dependsOn: [ + avdSharedResourcesRg + ] +} +// + +// Availability set +module avdAvailabilitySet '../carml/1.0.0/Microsoft.Compute/availabilitySets/deploy.bicep' = if (!avdUseAvailabilityZones && avdDeploySessionHosts) { + name: 'AVD-Availability-Set-${time}' + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdComputeObjectsRgName}') + params: { + name: avdAvailabilitySetName + location: avdSessionHostLocation + availabilitySetFaultDomain: 3 + availabilitySetUpdateDomain: 5 + } + dependsOn: [ + avdComputeObjectsRg + ] +} + +// Session hosts + +// Session hosts +// Call on the KV. +resource avdWrklKeyVaultget 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = if (avdDeploySessionHosts) { + name: avdWrklKvName + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') +} +/* +resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2021-01-14-preview' existing = { + name: avdHostPoolName + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdServiceObjectsRgName}') +} +*/ +module avdSessionHosts '../carml/1.0.0/Microsoft.Compute/virtualMachines/deploy.bicep' = [for i in range(0, avdDeploySessionHostsCount): if (avdDeploySessionHosts) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdComputeObjectsRgName}') + name: 'AVD-Session-Host-${i}-${time}' + //wait: 30 + //retry: 5 + params: { + name: '${avdSessionHostNamePrefix}-${i}' + location: avdSessionHostLocation + systemAssignedIdentity: true + availabilityZone: avdUseAvailabilityZones ? take(skip(allAvailabilityZones, i % length(allAvailabilityZones)), 1) : [] + encryptionAtHost: encryptionAtHost + availabilitySetName: !avdUseAvailabilityZones ? (avdDeploySessionHosts ? avdAvailabilitySet.outputs.name : '') : '' + osType: 'Windows' + licenseType: 'Windows_Client' + vmSize: avdSessionHostsSize + imageReference: useSharedImage ? json('{\'id\': \'${avdImageTemplataDefinition.outputs.resourceId}\'}') : marketPlaceGalleryWindows[avdOsImage] + osDisk: { + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: 128 + managedDisk: { + storageAccountType: avdSessionHostDiskType + } + } + adminUsername: avdVmLocalUserName + adminPassword: avdVmLocalUserPassword //avdWrklKeyVaultget.getSecret('avdVmLocalUserPassword') //avdVmLocalUserPassword // need to update to get value from KV + nicConfigurations: [ + { + nicSuffix: '-nic-01' + deleteOption: 'Delete' + asgId: createAvdVnet ? '${avdApplicationSecurityGroup.outputs.resourceId}' : null + enableAcceleratedNetworking: false + ipConfigurations: [ + { + name: 'ipconfig01' + //subnetId: createAvdVnet ? '${avdVirtualNetwork.outputs.resourceId}/subnets/${avdVnetworkSubnetName}' : '${existingVnetResourceId}/subnets/${existingVnetSubnetName}' + subnetId: createAvdVnet ? '${avdVirtualNetwork.outputs.resourceId}/subnets/${avdVnetworkSubnetName}' : existingVnetSubnetResourceId + } + ] + } + ] + // Join domain + allowExtensionOperations: true + extensionDomainJoinPassword: avdDomainJoinUserPassword //avdWrklKeyVaultget.getSecret('avdDomainJoinUserPassword') + extensionDomainJoinConfig: { + enabled: true + settings: { + name: avdIdentityDomainName + //enableAutomaticUpgrade: true + ouPath: !empty(avdOuPath) ? avdOuPath : null + user: avdDomainJoinUserName + restart: 'true' + options: '3' + } + } + // Enable and Configure Microsoft Malware + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: true + RealtimeProtectionEnabled: 'true' + //enableAutomaticUpgrade: true + ScheduledScanSettings: { + isEnabled: 'true' + day: '7' // Day of the week for scheduled scan (1-Sunday, 2-Monday, ..., 7-Saturday) + time: '120' // When to perform the scheduled scan, measured in minutes from midnight (0-1440). For example: 0 = 12AM, 60 = 1AM, 120 = 2AM. + scanType: 'Quick' //Indicates whether scheduled scan setting type is set to Quick or Full (default is Quick) + } + Exclusions: { + Extensions: '*.vhd;*.vhdx' + Paths: '"%ProgramFiles%\\FSLogix\\Apps\\frxdrv.sys;%ProgramFiles%\\FSLogix\\Apps\\frxccd.sys;%ProgramFiles%\\FSLogix\\Apps\\frxdrvvt.sys;%TEMP%\\*.VHD;%TEMP%\\*.VHDX;%Windir%\\TEMP\\*.VHD;%Windir%\\TEMP\\*.VHDX;\\\\server\\share\\*\\*.VHD;\\\\server\\share\\*\\*.VHDX' + Processes: '%ProgramFiles%\\FSLogix\\Apps\\frxccd.exe;%ProgramFiles%\\FSLogix\\Apps\\frxccds.exe;%ProgramFiles%\\FSLogix\\Apps\\frxsvc.exe' + } + } + } + } + dependsOn: [ + avdComputeObjectsRg + avdWrklKeyVault + avdWrklKeyVaultget + imageTemplateBuildCheck + ] +}] +// Add session hosts to AVD Host pool. +module addAvdHostsToHostPool '../carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/add-avd-session-hosts.bicep' = [for i in range(0, avdDeploySessionHostsCount): if (avdDeploySessionHosts) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdComputeObjectsRgName}') + name: 'Add-AVD-Session-Host-${i}-to-HostPool-${time}' + params: { + location: avdSessionHostLocation + hostPoolToken: '${avdHostPool.outputs.hostPoolRestrationInfo.token}' + name: '${avdSessionHostNamePrefix}-${i}' + hostPoolName: avdHostPoolName + avdAgentPackageLocation: avdAgentPackageLocation + } + dependsOn: [ + avdSessionHosts + avdHostPool + ] +}] + +// Add the registry keys for Fslogix. Alternatively can be enforced via GPOs +module configureFsLogixForAvdHosts '../carml/1.0.0/Microsoft.Compute/virtualMachines/extensions/configure-fslogix-session-hosts.bicep' = [for i in range(0, avdDeploySessionHostsCount): if (avdDeploySessionHosts) { + scope: resourceGroup('${avdWrklSubscriptionId}', '${avdComputeObjectsRgName}') + name: 'Configure-FsLogix-for-${avdSessionHostNamePrefix}-${i}-${time}' + params: { + location: avdSessionHostLocation + name: '${avdSessionHostNamePrefix}-${i}' + file: fsLogixScript + FsLogixScriptArguments: FsLogixScriptArguments + baseScriptUri: fslogixScriptUri + } + dependsOn: [ + avdSessionHosts + ] +}] + +// + +// ======= // +// Outputs // +// ======= // +/* +output avdSharedResourcesRgId string = avdSharedResourcesRg.outputs.resourceId +output avdServiceObjectsRgId string = avdServiceObjectsRg.outputs.resourceId +output adNetworkObjectsRgId string = avdNetworkObjectsRg.outputs.resourceId +output avdComputeObjectsRgId string = avdComputeObjectsRg.outputs.resourceId +output avdStorageObjectsRgId string = avdStorageObjectsRg.outputs.resourceId +output avdApplicationGroupId string = avdApplicationGroup.outputs.resourceId +output avdHPoolId string = avdHostPool.outputs.resourceId +output azureImageBuilderRoleId string = azureImageBuilderRole.outputs.resourceId +output aibManagedIdentityNameId string = imageBuilderManagedIdentity.outputs.principalId +output avdVirtualNetworkId string = avdVirtualNetwork.outputs.resourceId +output avdNetworksecurityGroupId string = avdNetworksecurityGroup.outputs.resourceId +output fslogixStorageId string = fslogixStorage.outputs.resourceId +*/ diff --git a/workload/docs/diagrams/avd-accelerator-baseline-architecture.vsdx b/workload/docs/diagrams/avd-accelerator-baseline-architecture.vsdx new file mode 100644 index 000000000..4f4da214f Binary files /dev/null and b/workload/docs/diagrams/avd-accelerator-baseline-architecture.vsdx differ diff --git a/workload/docs/diagrams/avd-accelerator-baseline-networking-scenario.vsdx b/workload/docs/diagrams/avd-accelerator-baseline-networking-scenario.vsdx new file mode 100644 index 000000000..9225afc11 Binary files /dev/null and b/workload/docs/diagrams/avd-accelerator-baseline-networking-scenario.vsdx differ diff --git a/workload/docs/diagrams/avd-accelerator-baseline.png b/workload/docs/diagrams/avd-accelerator-baseline.png new file mode 100644 index 000000000..30482a7ec Binary files /dev/null and b/workload/docs/diagrams/avd-accelerator-baseline.png differ diff --git a/workload/docs/diagrams/avd-accelerator-resource-organization-naming.vsdx b/workload/docs/diagrams/avd-accelerator-resource-organization-naming.vsdx new file mode 100644 index 000000000..bbf996b0d Binary files /dev/null and b/workload/docs/diagrams/avd-accelerator-resource-organization-naming.vsdx differ diff --git a/workload/portal-ui/portal-ui-baseline.json b/workload/portal-ui/portal-ui-baseline.json new file mode 100644 index 000000000..022686b0c --- /dev/null +++ b/workload/portal-ui/portal-ui-baseline.json @@ -0,0 +1,1094 @@ +{ + "$schema": "", + "view": { + "kind": "Form", + "properties": { + "title": "AVD landing zone accelerator - Baseline", + "steps": [ + { + "name": "basics", + "label": "Azure core setup", + "subLabel": { + "preValidation": "Provide deployment prefix for the resource groups and resources that will be created.", + "postValidation": "Done" + }, + "bladeTitle": "avdBasics", + "elements": [ + { + "name": "avdSharedServices", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Workload services baseline deployment", + "elements": [ + { + "name": "info", + "type": "Microsoft.Common.InfoBox", + "options": { + "text": "Subscription and location selected in this step, will be used to deploy AVD workload Landing Zone resources (Application group, host pool, workspace, key vaults, storage, VMs etc.).", + "style": "Info" + } + } + ] + }, + { + "name": "avdDeploymentScope", + "type": "Microsoft.Common.ResourceScope", + "location": { + "resourceTypes": [] + } + }, + { + "name": "avdWorkloadSubscription", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Azure AVD Landing Zones will create the resource group hierarchy under the subscriptions with the prefix provided at this step.", + "link": { + "label": "Learn more", + "uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/management-group-and-subscription-organization" + } + } + }, + { + "name": "avdDeploymentPrefix", + "type": "Microsoft.Common.TextBox", + "label": "Deployment prefix", + "toolTip": "Provide a prefix (max 4 characters) for the resource groups and resources created as part of AVD landing zones.", + "placeholder": "Example: App1", + "constraints": { + "required": true, + "regex": "^[a-z0-9A-Z-]{1,4}$", + "validationMessage": "The prefix must be 1-4 characters." + } + }, + { + "name": "roleinfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Azure AVD Landing Zones ARM deployment requires owner access at the subscription scope. Visit this link to get more information on RBAC permissions and scopes.", + "uri": "https://docs.microsoft.com/en-us/azure/role-based-access-control/scope-overview", + "style": "Warning" + } + } + ] + }, + { + "name": "avdManagementPlane", + "label": "Management plane", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdManagementPlane", + "elements": [ + { + "name": "avdManagementPlanelocation", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Location for: workspace, host pool and application groups metadata", + "elements": [ + { + "name": "avdManagementPlaneLocation", + "type": "Microsoft.Common.DropDown", + "visible": true, + "label": "Deployment location", + "defaultValue": "equals(steps('basics').avdDeploymentScope.location.displayName)", + "toolTip": "Select region where AVD workspace, host pool and application groups will be created.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Canada Central", + "value": "canadacentral" + }, + { + "label": "Canada East", + "value": "canadaeast" + }, + { + "label": "Central US", + "value": "centralus" + }, + { + "label": "East US", + "value": "eastus" + }, + { + "label": "East US 2", + "value": "eastus2" + }, + { + "label": "North Central US", + "value": "northcentralus" + }, + { + "label": "North Europe", + "value": "northeurope" + }, + { + "label": "South Central US", + "value": "southcentralus" + }, + { + "label": "UK South", + "value": "uksouth" + }, + { + "label": "UK West", + "value": "ukwest" + }, + { + "label": "West Central US", + "value": "westcentralus" + }, + { + "label": "West Europe", + "value": "westeurope" + }, + { + "label": "West India", + "value": "westindia" + }, + { + "label": "West US", + "value": "westus" + }, + { + "label": "West US 2", + "value": "westus2" + } + ] + } + } + ] + }, + { + "name": "hostPoolInfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Select the location where management plane resources (workspace, host pool, application groups) will be deployed, this resources are not available in all locations but are globally replicated and they can share the same location as the session hosts or not.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-desktop/data-locations", + "style": "Info" + } + }, + { + "name": "avdManagementPlaneHostPoolSettings", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Host pool settings", + "elements": [ + { + "name": "hostPoolType", + "type": "Microsoft.Common.DropDown", + "visible": true, + "label": "Host pool type", + "defaultValue": "Pooled", + "multiLine": true, + "toolTip": "", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Pooled", + "description": "", + "value": "Pooled" + }, + { + "label": "Personal", + "description": "", + "value": "Personal" + } + ] + } + }, + { + "name": "subWarning", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "icon": "Warning", + "text": "Host pool type can not be changed after deployment.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-desktop/environment-setup" + } + }, + { + "name": "loadBalancerType", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled')]", + "label": "Load balancer", + "defaultValue": "BreadthFirst", + "multiLine": true, + "toolTip": "Breadth-first load balancing distributes new user sessions across all available session hosts in the host pool. Depth-first load balancing distributes new user sessions to an available session host with the highest number of connections but has not reached its maximum session limit threshold.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "BreadthFirst", + "description": "Each new user is placed on the next VM. (Performance Optimized)", + "value": "BreadthFirst" + }, + { + "label": "DepthFirst", + "description": "Each new user is placed on the same VM until max sessions limit. (Cost Optimized)", + "value": "DepthFirst" + } + ] + } + }, + { + "name": "maxSessions", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled')]", + "label": "Max sessions", + "defaultValue": "10", + "toolTip": "The maximum number of users that have concurrent sessions on a session host. When setting a host pool to have depth first load balancing or planning to use Autoscaling, you must set an appropriate max session limit according to the configuration of your deployment and capacity of your VMs.", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "" + } + }, + { + "name": "assignmentType", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Personal')]", + "label": "Machine assignment", + "defaultValue": "Automatic (Recommended)", + "multiLine": true, + "toolTip": "Automatic assignment – The service will select an available host and assign it to an user. Direct assignment – Admin selects a specific host to assign to an user.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Automatic (Recommended)", + "description": "Users are assigned an available VM the first time they connect.", + "value": "Automatic" + }, + { + "label": "Direct", + "description": "An administrator assigns a VM for each individual user.", + "value": "Direct" + } + ] + } + } + ] + }, + { + "name": "avdManagementPlaneAppGroupOptions", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled')]", + "label": "Application group options (Desktop application group will be deployed by default)", + "elements": [ + { + "name": "avdDeployRappGroup", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Create remote app group", + "defaultValue": "Yes (Recommended)", + "toolTip": "This application group type allows to publish seamless apps instead of full desktops.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes (Recommended)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + } + ] + }, + { + "name": "avdManagementPlaneHostPoolScaling", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Session host scaling options", + "elements": [ + { + "name": "startVmOnConnect", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Start VM on connect", + "defaultValue": "Yes (Recommended)", + "toolTip": "If powered off, start VM once user connects. ", + "constraints": { + "required": false, + "allowedValues": [ + { + "label": "Yes (Recommended)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "createVmRole", + "type": "Microsoft.Common.OptionsGroup", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect, true)]", + "label": "Create start VM on connect role", + "defaultValue": "Yes (Required if using Start VM On Connect)", + "toolTip": "Create custom Azure IAM role for Start VM on Connect", + "constraints": { + "required": false, + "allowedValues": [ + { + "label": "Yes (Required if using Start VM On Connect)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdEnterApplication", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect, true)]", + "label": "AVD enterprise application ObjectID", + "defaultValue": "", + "toolTip": "Provide the ObjectID of the enterprise application Windows Virtual Desktop (ApplicationID: 9cdead84-a844-4324-93f2-b2e6bb768d07).", + "constraints": { + "required": true + } + }, + { + "name": "vmRoleWarning", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole, false)]", + "options": { + "text": "Start VM on Connect will not work without a custom role definition. If you enable start on connect, but do not specify a custom role VM's will not start on-demand. Only select no if this custom role already exists and is assigned to your AVD subscription.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-desktop/start-virtual-machine-connect", + "style": "Warning" + } + } + ] + } + ] + }, + { + "name": "avdSessionHosts", + "label": "Session Hosts", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdSessionHosts", + "elements": [ + { + "name": "avdDeploySessionHosts", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Deploy session hosts", + "defaultValue": "Yes", + "toolTip": "Create session hosts compute and storage resources.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdSessionHostsComputeStorageSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdSessionHosts').avdDeploySessionHosts, true)]", + "label": "General settings", + "tooltip": "This settings apply to compute, storage, image management and key vault resources.", + "elements": [ + { + "name": "avdSessionHostsAvailabilitySettings", + "type": "Microsoft.Common.OptionsGroup", + "label": "Use availability zones", + "defaultValue": "No", + "toolTip": "Distribute compute and storage resources across availability zones. When selecting No a availability set will be created to host the VMs.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdStorageAccountSku", + "type": "Microsoft.Common.DropDown", + "label": "File share sku", + "filter": true, + "defaultValue": "Premium_LRS", + "toolTip": "Storage account SKU for FSLogix storage. Recommended tier is Premium_ZRS when avaiable otherwise Premium_LRS.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Premium_LRS", + "description": "", + "value": "Premium_LRS" + }, + { + "label": "Premium_ZRS (When available)", + "description": "", + "value": "Premium_ZRS" + }, + { + "label": "Standard_LRS", + "description": "", + "value": "Standard_LRS" + }, + { + "label": "Standard_ZRS (When available)", + "description": "", + "value": "Standard_ZRS" + } + ] + } + }, + { + "name": "avdSessionHostsFslogixFileShareQuota", + "type": "Microsoft.Common.Slider", + "label": "Fslogix file share size", + "subLabel": "x 100GB", + "toolTip": "Size of Premium File share storage in 10GB increments", + "min": 1, + "max": 100, + "defaultValue": 1, + "showStepMarkers": true, + "constraints": { + "required": true + } + } + ] + }, + { + "name": "avdSessionHostsSettingsSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdSessionHosts').avdDeploySessionHosts, true)]", + "label": "Session hosts settings", + "elements": [ + { + "name": "element1", + "type": "Microsoft.Compute.SizeSelector", + "label": "VM Size", + "toolTip": "", + "recommendedSizes": [ + "Standard_D1", + "Standard_D2", + "Standard_D3" + ], + "constraints": { + "allowedSizes": [], + "excludedSizes": [], + "required": true + }, + "options": { + "hideDiskTypeFilter": true + }, + "osPlatform": "Windows", + "imageReference": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-11", + "sku": "21h2-avd" + } + }, + { + "name": "avdSessionHostsCount", + "type": "Microsoft.Common.TextBox", + "label": "VM count", + "toolTip": "Provide the number of session hosts to deploy (1-49).", + "defaultValue": 1, + "constraints": { + "required": true, + "regex": "^([1-9]|[1-4][0-9])$", + "validationMessage": "The count must be between 1-49 session hosts." + } + }, + { + "name": "avdSessionHostDiskType", + "type": "Microsoft.Common.DropDown", + "label": "OS Disk type", + "filter": true, + "defaultValue": "Standard", + "toolTip": "Select session host disk type to host the OS.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Standard", + "value": "Standard_LRS" + }, + { + "label": "Premium", + "value": "Premium_LRS" + } + ] + } + }, + { + "name": "avdSessionHostEncryptionAtHost", + "type": "Microsoft.Common.OptionsGroup", + "label": "End to end encryption (encryptionAtHost)", + "defaultValue": "No", + "toolTip": "When you enable encryption at host, data stored on the VM host is encrypted at rest and flows encrypted to the Storage service. For conceptual information on encryption at host, and other managed disk encryption types.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdSessionHostEncryptionAtHostWarning", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostEncryptionAtHost, true)]", + "options": { + "text": "Encryption at host requires feature EncryptionAtHost of resource provider Microsoft.Compute to be registered in the subscription.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-machines/disks-enable-host-based-encryption-portal?msclkid=31c2d29bbce111ec8bca8257221ab9d1", + "style": "Warning" + } + } + ] + }, + { + "name": "avdSessionHostsOsSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdSessionHosts').avdDeploySessionHosts, true)]", + "label": "OS selection", + "elements": [ + { + "name": "avdSessionHostsImageSource", + "type": "Microsoft.Common.DropDown", + "label": "OS image source", + "filter": true, + "defaultValue": "Marketplace", + "toolTip": "Select marketplace or build custom image to deploy the session hosts.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Marketplace", + "value": false + }, + { + "label": "Compute Gallery", + "value": true + } + ] + } + }, + { + "name": "avdSessionHostsOsImage", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsImageSource, false)]", + "label": "OS version", + "filter": true, + "defaultValue": "Windows 11", + "toolTip": "Select OS version to deploy the session hosts with.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Windows 10", + "value": "win10_21h2" + }, + { + "label": "Windows 10 - Office 365", + "value": "win10_21h2_office" + }, + { + "label": "Windows 11", + "value": "win11_21h2" + }, + { + "label": "Windows 11 - Office 365", + "value": "win11_21h2_office" + } + ] + } + }, + { + "name": "avdSessionHostsComputeGalleryImage", + "type": "Microsoft.Solutions.ResourceSelector", + "visible": "[equals(steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsImageSource, true)]", + "label": "Image", + "resourceType": "Microsoft.Compute/galleries/images", + "constraints": { + "required": true + } + } + ] + } + ] + }, + { + "name": "avdIdentity", + "label": "Identity", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdIdentitySettings", + "elements": [ + { + "name": "identityInfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "AVD landing zone accelerator deployment expects identity service to be already available in the current Azure estate.", + "uri": "https://docs.microsoft.com/azure/virtual-desktop/authentication#identities", + "style": "Info" + } + }, + { + "name": "avdIdentityDomainInformation", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Domain information", + "elements": [ + { + "name": "avdIdentityDomainName", + "type": "Microsoft.Common.TextBox", + "label": "Domain", + "toolTip": "Provide username with permissions to join session host to the domain.", + "placeholder": "Example: contoso.com", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityDomainOuPath", + "type": "Microsoft.Common.TextBox", + "label": "Session hosts OU path (Optional)", + "toolTip": "Provide OU where to locate session hosts, if not provided session hosts will be placed on the default (computers) OU.", + "placeholder": "Example: OU=avd,DC=contoso,DC=com", + "constraints": {} + }, + { + "name": "avdIdentityDomainOuPathBool", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Create OU for storage (fslogix)", + "defaultValue": "No", + "toolTip": "It is recommended to create a new AD Organizational Unit (OU) in AD and disable password expiration policy on computer accounts or service logon accounts accordingly.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdIdentityDomainOuPathStorage", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPathBool, true)]", + "label": "New storage OU name", + "toolTip": "OU will be created and used to locate storage account file share.", + "placeholder": "Example: avdstorage", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityDomainOuPathStorageExisting", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPathBool, false)]", + "label": "Existing storage OU name (Optional)", + "toolTip": "Provide OU where to locate storage account file share, if not provided session hosts will be placed on the default (computers) OU.", + "placeholder": "Example: avdstorage", + "constraints": {} + } + ] + }, + { + "name": "avdIdentityDomainCredentials", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Domain join credentials", + "elements": [ + { + "name": "avdIdentityDomainJoinUserName", + "type": "Microsoft.Common.TextBox", + "label": "Username", + "toolTip": "Provide username with permissions to join session host to the domain.", + "placeholder": "Example: avdadmin@contoso.com", + "defaultValue": "", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityDomainJoinUserPassword", + "type": "Microsoft.Common.PasswordBox", + "visible": true, + "label": { + "password": "Password" + }, + "toolTip": "Provide password for domain join account.", + "constraints": { + "required": true + }, + "options": { + "hideConfirmation": false + } + } + ] + }, + { + "name": "avdIdentityLocalCredentials", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Session host local admin credentials", + "elements": [ + { + "name": "avdIdentityLocalUserName", + "type": "Microsoft.Common.TextBox", + "label": "Username", + "toolTip": "Provide username for session host local admin account.", + "placeholder": "Example: avdadmin", + "defaultValue": "", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityLocalUserPassword", + "type": "Microsoft.Compute.CredentialsCombo", + "visible": true, + "label": { + "password": "Password", + "confirmPassword": "Confirm password" + }, + "toolTip": { + "password": "The password must be alphanumeric, contain at least 12 characters, have at least 1 letter,1 number and 1 special character." + }, + "constraints": { + "required": true, + "customPasswordRegex": "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=_!*<>()])(?=\\S+$).{12,123}$", + "customValidationMessage": "Password must include 1 special character." + }, + "options": { + "hideConfirmation": false + }, + "osPlatform": "Windows" + } + ] + } + ] + }, + { + "name": "avdNetwork", + "label": "Network connectivity", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "vnetInfoBox", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "AVD landing zone accelerator requires connectivity to identity services (ADDS or AADDS).", + "uri": "https://docs.microsoft.com/azure/virtual-desktop/authentication", + "style": "info" + } + }, + { + "name": "createAvdVnet", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Virtual network", + "defaultValue": "New", + "toolTip": "", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "New", + "value": true + }, + { + "label": "Existing", + "value": false + } + ] + } + }, + { + "name": "avdVnetSize", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "vNet address range", + "toolTip": "Virtual network for AVD virtual machines", + "placeholder": "Example: 10.10.0.0/23", + "constraints": { + "required": true, + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "validationMessage": "Invalid CIDR range. The address prefix must be in the range 10 to 24." + } + }, + { + "name": "avdVnetSubnetSize", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "Subnet address prefix", + "toolTip": "Virtual network subnet for AVD virtual machines", + "placeholder": "Example: 10.10.0.0/23", + "constraints": { + "required": true, + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "validationMessage": "Invalid CIDR range. The address prefix must be in the range 10 to 24." + } + }, + { + "name": "avdVnetDns", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "Custom DNS Servers", + "defaultValue": "", + "placeholder": "Example: 10.10.100.4, 10.20.100.5", + "toolTip": "If using custom DNS servers, enter multiple IPs separated by a comma.", + "constraints": { + "regex": "" + } + }, + { + "name": "avdVnetPrivateDnsZone", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Azure private DNS zone (Private endpoints)", + "defaultValue": "No", + "toolTip": "It is recommended to use Azure private DNS zones for private endpoint name spaces (ALZ recommended and deployed).", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdVnetPrivateDnsZoneFilesSelector", + "type": "Microsoft.Solutions.ResourceSelector", + "visible": "[equals(steps('avdNetwork').avdVnetPrivateDnsZone, true)]", + "label": "File share (privatelink.file.core.windows.net)", + "resourceType": "Microsoft.Network/privateDnsZones", + "constraints": { + "required": true + } + }, + { + "name": "avdVnetPrivateDnsZoneKeyvaultSelector", + "type": "Microsoft.Solutions.ResourceSelector", + "visible": "[equals(steps('avdNetwork').avdVnetPrivateDnsZone, true)]", + "label": "Key vault (privatelink.vaultcore.azure.net)", + "resourceType": "Microsoft.Network/privateDnsZones", + "constraints": { + "required": true + } + }, + { + "name": "avdVnetPeeringInfoBox", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "options": { + "text": "vNet peering will be created to existing vNet hub with access to identity and DNS services .", + "uri": "https://docs.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?context=/azure/virtual-desktop/context/context", + "style": "info" + } + }, + { + "name": "avdHubVnetPeering", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "Existing hub vNet peering information", + "elements": [ + { + "name": "avdHubVnetSelector", + "type": "Microsoft.Solutions.ResourceSelector", + "label": "Virtual Network", + "resourceType": "Microsoft.Network/virtualNetworks", + "constraints": { + "required": true + } + }, + { + "name": "avdHubVnetGateway", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Gateway on hub", + "defaultValue": "No", + "toolTip": "This information will be used to set remote gateway settings on vNet peering.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + } + ] + }, + { + "name": "avdExistingVnetInfoBox", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "options": { + "text": "Existing network must has connectivity to identity and DNS services.", + "uri": "https://docs.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?context=/azure/virtual-desktop/context/context", + "style": "info" + } + }, + { + "name": "avdVnetSelectorId", + "type": "Microsoft.Solutions.ResourceSelector", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "label": "Virtual network", + "resourceType": "Microsoft.Network/virtualNetworks", + "constraints": { + "required": true + }, + "options": { + "filter": { + "subscription": "onBasics", + "location": "onBasics" + } + } + }, + { + "name": "avdSubnetApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "[concat(steps('avdNetwork').avdVnetSelectorId.id, '/subnets?api-version=2021-03-01')]" + } + }, + { + "name": "avdVnetSubnetSelectorName", + "label": "Subnet", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "defaultValue": "", + "toolTip": "Select the subnet.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('avdNetwork').avdSubnetApi.value,(item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\",\"description\":\"', 'Resource Group: ', last(take(split(item.id, '/'), 5)), '\"}')))]", + "required": true + } + }, + { + "name": "avdExistingVnetInfoBoxPrivateEndpointWarning", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "options": { + "text": "Private endpoint network policy needs to be disabled on the existing subnet before deploying AVD accelerator.", + "uri": "https://docs.microsoft.com/azure/private-link/disable-private-endpoint-network-policy", + "style": "Warning" + } + } + ] + } + ] + }, + "outputs": { + "parameters": { + "deploymentPrefix": "[steps('basics').avdDeploymentPrefix]", + "avdSessionHostLocation": "[steps('basics').avdDeploymentScope.location.name]", + "fsLogixStorageSku": "[if(equals(steps('avdSessionHosts').avdDeploySessionHosts, true), steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdStorageAccountSku, 'none')]", + "avdManagementPlaneLocation": "[steps('avdManagementPlane').avdManagementPlanelocation.avdManagementPlaneLocation]", + "avdWorkloadSubsId": "[steps('basics').avdDeploymentScope.subscription.subscriptionId]", + "avdHostPoolType": "[steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType]", + "avdHostPoolLoadBalancerType": "[steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.loadBalancerType]", + "avhHostPoolMaxSessions": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled'), steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.maxSessions, 1)]", + "avdPersonalAssignType": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Personal'), steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.assignmentType, 'Automatic')]", + "avdDeployRappGroup": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled'), steps('avdManagementPlane').avdManagementPlaneAppGroupOptions.avdDeployRappGroup, 'none')]", + "avdIdentityDomainName": "[steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainName]", + "avdOuPath": "[steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPath]", + "avdDomainJoinUserName": "[steps('avdIdentity').avdIdentityDomainCredentials.avdIdentityDomainJoinUserName]", + "avdDomainJoinUserPassword": "[steps('avdIdentity').avdIdentityDomainCredentials.avdIdentityDomainJoinUserPassword]", + "avdVmLocalUserName": "[steps('avdIdentity').avdIdentityLocalCredentials.avdIdentityLocalUserName]", + "avdVmLocalUserPassword": "[steps('avdIdentity').avdIdentityLocalCredentials.avdIdentityLocalUserPassword.password]", + "createAvdVnet": "[steps('avdNetwork').createAvdVnet]", + "avdVnetworkAddressPrefixes": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdVnetSize, '10.10.0.0/23')]", + "avdVnetworkSubnetAddressPrefix": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdVnetSubnetSize, '10.10.0.0/23')]", + "customDnsIps": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdVnetDns, '')]", + "existingHubVnetResourceId": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdHubVnetPeering.avdHubVnetSelector.id, 'none')]", + "vNetworkGatewayOnHub": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdHubVnetPeering.avdHubVnetGateway, false)]", + "existingVnetSubnetResourceId": "[if(equals(steps('avdNetwork').createAvdVnet, false), steps('avdNetwork').avdVnetSubnetSelectorName, 'none')]", + "avdDeploySessionHosts": "[steps('avdSessionHosts').avdDeploySessionHosts]", + "avdStartVmOnConnect": "[steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect]", + "createStartVmOnConnectCustomRole": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect, true), steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole, false)]", + "avdEnterpriseAppObjectId": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole, true), steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.avdEnterApplication.objectId, 'none')]", + "avdUseAvailabilityZones": "[steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdSessionHostsAvailabilitySettings]", + "avdDeploySessionHostsCount": "[if(equals(steps('avdSessionHosts').avdDeploySessionHosts, true), steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostsCount, 1)]", + "useSharedImage": "[if(equals(steps('avdSessionHosts').avdDeploySessionHosts, true), steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsImageSource, false)]", + "avdOsImage": "[if(equals(steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsImageSource, false), steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsOsImage, 'win11_21h2')]", + "avdImageTemplataDefinitionId": "[if(equals(steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsImageSource, true), steps('avdSessionHosts').avdSessionHostsOsSection.avdSessionHostsComputeGalleryImage.id, 'none')]", + "avdSessionHostDiskType": "[steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostDiskType]", + "encryptionAtHost": "[steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostEncryptionAtHost]", + "avdSessionHostsSize": "[if(equals(steps('avdSessionHosts').avdDeploySessionHosts, true), steps('avdSessionHosts').avdSessionHostsSettingsSection.element1, 'Standard_D2s_v4')]", + "avdFslogixFileShareQuotaSize": "[steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdSessionHostsFslogixFileShareQuota]", + "createOuForStorage": "[steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPathBool]", + "storageOuName": "[if(equals(steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPathBool, true), steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPathStorage, steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPathStorageExisting)]", + "avdVnetPrivateDnsZone": "[steps('avdNetwork').avdVnetPrivateDnsZone]", + "avdVnetPrivateDnsZoneFilesId": "[if(equals(steps('avdNetwork').avdVnetPrivateDnsZone, true), steps('avdNetwork').avdVnetPrivateDnsZoneFilesSelector.id, '')]", + "avdVnetPrivateDnsZoneKeyvaultId": "[if(equals(steps('avdNetwork').avdVnetPrivateDnsZone, true), steps('avdNetwork').avdVnetPrivateDnsZoneKeyvaultSelector.id, '')]" + }, + "kind": "Subscription", + "location": "[steps('basics').avdDeploymentScope.location.name]", + "subscriptionId": "[steps('basics').avdDeploymentScope.subscription.id]" + } + } +} \ No newline at end of file diff --git a/workload/portal-ui/portal-ui-custom-image.json b/workload/portal-ui/portal-ui-custom-image.json new file mode 100644 index 000000000..f21350268 --- /dev/null +++ b/workload/portal-ui/portal-ui-custom-image.json @@ -0,0 +1,323 @@ +{ + "$schema": "", + "view": { + "kind": "Form", + "properties": { + "title": "AVD landing zone accelerator - Custom image build", + "steps": [ + { + "name": "basics", + "label": "Azure core setup", + "subLabel": "", + "bladeTitle": "avdBasics", + "elements": [ + { + "name": "avdSharedServices", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Shared services baseline deployment", + "elements": [ + { + "name": "info", + "type": "Microsoft.Common.InfoBox", + "options": { + "text": "Subscription and location selected in this step, will be used to deploy AVD Shared Services Landing Zone resources (compute gallery, key vaults, storage, AIB etc.).", + "style": "Info" + } + } + ] + }, + { + "name": "avdDeploymentScope", + "type": "Microsoft.Common.ResourceScope", + "location": { + "resourceTypes": [] + } + }, + { + "name": "avdDeploymentPrefix", + "type": "Microsoft.Common.TextBox", + "visible": true, + "label": "Deployment prefix", + "toolTip": "Provide a prefix (max 4 characters) for the resource groups and resources created as part of AVD landing zones.", + "placeholder": "Example: App1", + "constraints": { + "required": true, + "regex": "^[a-z0-9A-Z-]{1,4}$", + "validationMessage": "The prefix must be 1-4 characters." + } + }, + { + "name": "roleinfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Azure AVD Landing Zones ARM deployment requires owner access at the subscription scope. Visit this link to get more information on RBAC permissions and scopes.", + "uri": "https://docs.microsoft.com/en-us/azure/role-based-access-control/scope-overview", + "style": "Warning" + } + } + ] + }, + { + "name": "avdCustomImage", + "label": "Image management", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdCustomImage", + "elements": [ + { + "name": "avdCustomImageInfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Custom image automation will deploy a compute gallery, images, storage, identity and run an Azure image Builder job.", + "style": "Info" + } + }, + { + "name": "avdCustomImageStorageSelection", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Storage", + "elements": [ + { + "name": "avdCustomImageStorageAvailability", + "type": "Microsoft.Common.OptionsGroup", + "label": "Use availability zones", + "defaultValue": "No", + "toolTip": "Distribute storage resources across availability zones.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes (When available)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + } + ] + }, + { + "name": "avdCustomImageOsSelection", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "OS", + "elements": [ + { + "name": "avdCustomImageOsImage", + "type": "Microsoft.Common.DropDown", + "label": "Version", + "filter": true, + "defaultValue": "Windows 11", + "toolTip": "Select OS version to be used as source for the image.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Windows 10", + "value": "win10_21h2" + }, + { + "label": "Windows 10 - Office 365", + "value": "win10_21h2_office" + }, + { + "label": "Windows 11", + "value": "win11_21h2" + }, + { + "label": "Windows 11 - Office 365", + "value": "win11_21h2_office" + } + ] + } + } + ] + } + ] + }, + { + "name": "avdCustomImageAib", + "label": "Azure Image Builder (AIB)", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdCustomImageAibInfo", + "elements": [ + { + "name": "avdCustomImageInfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Azure Image Builder is not available on all locations.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-machines/image-builder-overview?msclkid=06a023c8ac4c11ecb3c259d74812c2c6", + "style": "Info" + } + }, + { + "name": "avdCustomImageLocation", + "type": "Microsoft.Common.DropDown", + "visible": true, + "label": "Deployment location", + "defaultValue": "equals(steps('basics').avdDeploymentScope.location.displayName)", + "toolTip": "Select the location where Azure Image Builder will run to create the image.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "East US", + "value": "eastus" + }, + { + "label": "East US 2", + "value": "eastus2" + }, + { + "label": "West Central US", + "value": "westcentralus" + }, + { + "label": "West US", + "value": "westus" + }, + { + "label": "West US 2", + "value": "westus2" + }, + { + "label": "West US 3", + "value": "westus3" + }, + { + "label": "South Central US", + "value": "southcentralus" + }, + { + "label": "North Europe", + "value": "northeurope" + }, + { + "label": "West Europe", + "value": "westeurope" + }, + { + "label": "UK South", + "value": "uksouth" + }, + { + "label": "UK West", + "value": "ukwest" + }, + { + "label": "South East Asia", + "value": "southeastasia" + }, + { + "label": "Australia South East", + "value": "australiasoutheast" + }, + { + "label": "Australia East", + "value": "australiaeast" + } + ] + } + }, + { + "name": "avdCustomImageIdentityAibCreateManagedIdentity", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Create AIB managed identity", + "defaultValue": "Yes", + "toolTip": "Create managed identity for Azure Image Builder custom role.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdCustomImageIdentityAibSelectManagedIdentity", + "type": "Microsoft.Solutions.ResourceSelector", + "visible": "[equals(steps('avdCustomImageAib').avdCustomImageIdentityAibCreateManagedIdentity, false)]", + "label": "Existing managed identity", + "resourceType": "Microsoft.ManagedIdentity/userAssignedIdentities", + "constraints": { + "required": true + }, + "options": { + "filter": { + "subscription": "onBasics" + } + } + }, + { + "name": "avdCustomImageIdentityAibCreateRole", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Create AIB role", + "defaultValue": "Yes", + "toolTip": "Create Azure Image Builder custom role.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "roleinfo", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdCustomImageAib').avdCustomImageIdentityAibCreateRole, false)]", + "options": { + "text": "A role with the name AzureImageBuilder-AVD must already exist.", + "style": "Warning" + } + } + ] + } + ] + }, + "outputs": { + "parameters": { + "deploymentPrefix": "[steps('basics').avdDeploymentPrefix]", + "avdSharedServicesLocation": "[steps('basics').avdDeploymentScope.location.name]", + "avdSharedServicesSubId": "[steps('basics').avdDeploymentScope.subscription.subscriptionId]", + "avdUseAvailabilityZones": "[steps('avdCustomImage').avdCustomImageStorageSelection.avdCustomImageStorageAvailability]", + "createAibManagedIdentity": "[steps('avdCustomImageAib').avdCustomImageIdentityAibCreateManagedIdentity]", + "existingAibManagedIdentityId": "[if(equals(steps('avdCustomImageAib').avdCustomImageIdentityAibCreateManagedIdentity, false), steps('avdCustomImageAib').avdCustomImageIdentityAibSelectManagedIdentity.id, 'none')]", + "existingAibManagedIdentityName": "[if(equals(steps('avdCustomImageAib').avdCustomImageIdentityAibCreateManagedIdentity, false), steps('avdCustomImageAib').avdCustomImageIdentityAibSelectManagedIdentity.name, 'none')]", + "createAibCustomRole": "[steps('avdCustomImageAib').avdCustomImageIdentityAibCreateRole]", + "aibLocation": "[steps('avdCustomImageAib').avdCustomImageLocation]", + "avdOsImage": "[steps('avdCustomImage').avdCustomImageOsSelection.avdCustomImageOsImage]" + }, + "kind": "Subscription", + "location": "[steps('basics').avdDeploymentScope.location.name]", + "subscriptionId": "[steps('basics').avdDeploymentScope.subscription.id]" + } + } +} diff --git a/workload/portal-ui/portal-ui.json b/workload/portal-ui/portal-ui.json new file mode 100644 index 000000000..91d1019d7 --- /dev/null +++ b/workload/portal-ui/portal-ui.json @@ -0,0 +1,1036 @@ +{ + "$schema": "", + "view": { + "kind": "Form", + "properties": { + "title": "AVD landing zone accelerator", + "steps": [ + { + "name": "basics", + "label": "Deployment location", + "elements": [ + { + "name": "resourceScope", + "type": "Microsoft.Common.ResourceScope" + } + ] + }, + { + "name": "avdLzSettings", + "label": "Azure core setup", + "subLabel": { + "preValidation": "Provide deployment prefix for the resource groups and resources that will be created.", + "postValidation": "Done" + }, + "bladeTitle": "Deployment prefix", + "elements": [ + { + "name": "info", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "Azure AVD Landing Zones ARM deployment requires owner access at the subscription scope. Visit this link to get more information on RBAC permissions and scopes.", + "uri": "https://docs.microsoft.com/en-us/azure/role-based-access-control/scope-overview", + "style": "Info" + } + }, + { + "name": "avdWorkloadSubscription", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Azure AVD Landing Zones will create the resource group hierarchy under the subscriptions with the prefix provided at this step.", + "link": { + "label": "Learn more", + "uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/management-group-and-subscription-organization" + } + } + }, + { + "name": "avdDeploymentPrefix", + "type": "Microsoft.Common.TextBox", + "label": "Deployment prefix", + "toolTip": "Provide a prefix (max 4 characters) for the resource groups and resources created as part of AVD landing zones.", + "placeholder": "Example: App1", + "constraints": { + "required": true, + "regex": "^[a-z0-9A-Z-]{1,4}$", + "validationMessage": "The prefix must be 1-4 characters." + } + }, + { + "name": "avdSubOrgsOption", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Subscription deployment model", + "defaultValue": "Multiple (recommended)", + "toolTip": "If 'Multiple' is selected, deployment will use two subscriptions (AVD landing zone and AVD shared Services Landing zone).", + "constraints": { + "allowedValues": [ + { + "label": "Multiple (recommended)", + "value": "Multiple" + }, + { + "label": "Single", + "value": "Single" + } + ] + } + }, + { + "name": "avdSingleSubSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdLzSettings').avdSubOrgsOption, 'Single')]", + "label": "Single subscription deployment", + "elements": [ + { + "name": "subWarning", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "icon": "Warning", + "text": "Multiple subscriptions are recommended for the various components to ensure scale, sustainability, and segregation of duties. However, a single subscription can also be used in case this is not a concern (e.g., small enterprises).", + "uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/management-group-and-subscription-organization" + } + }, + { + "name": "singleSubText", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Select the dedicated, single subscription that will be used for all AVD resources during deployment (AVD workload and shared services resources)." + } + }, + { + "name": "avdSingleSub", + "type": "Microsoft.Common.SubscriptionSelector", + "label": "Single platform subscription" + } + ] + }, + { + "name": "avdMultipleSubSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdLzSettings').avdSubOrgsOption, 'Multiple')]", + "label": "Multiple subscriptions deployment", + "elements": [ + { + "name": "multipleSubText", + "type": "Microsoft.Common.TextBlock", + "visible": true, + "options": { + "text": "Select the subscriptions, AVD Shared Services Landing Zone for shared platform resources (compute gallery, key vaults, storage, etc.) and AVD Landing zone for workload specific resources (VMs, AVD management plane, etc.) ." + } + }, + { + "name": "avdMultipleSubSectionSharedSub", + "type": "Microsoft.Common.Section", + "label": "AVD shared services", + "elements": [] + }, + { + "name": "avdMultipleSubShared", + "type": "Microsoft.Common.SubscriptionSelector", + "label": "Multiple platform subscription AVD shared services" + }, + { + "name": "avdMultipleSubSectionWorkloadSub", + "type": "Microsoft.Common.Section", + "label": "AVD workload", + "elements": [] + }, + { + "name": "avdMultipleSubWorkload", + "type": "Microsoft.Common.SubscriptionSelector", + "label": "Multiple platform subscription AVD workload" + } + ] + } + ] + }, + { + "name": "avdManagementPlane", + "label": "Management plane", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdManagementPlane", + "elements": [ + { + "name": "hostPoolInfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "A host pool is a collection of virtual machines deployed from the same base image and governed by the same properties.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-desktop/environment-setup#host-pools", + "style": "Info" + } + }, + { + "name": "avdManagementPlaneLocation", + "type": "Microsoft.Common.DropDown", + "visible": true, + "label": "Deployment location", + "defaultValue": "East US 2", + "toolTip": "Select region where AVD workspace, host pool and application groups will be created.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Canada Central", + "value": "canadacentral" + }, + { + "label": "Canada East", + "value": "canadaeast" + }, + { + "label": "Central US", + "value": "centralus" + }, + { + "label": "East US", + "value": "eastus" + }, + { + "label": "East US 2", + "value": "eastus2" + }, + { + "label": "North Central US", + "value": "northcentralus" + }, + { + "label": "North Europe", + "value": "northeurope" + }, + { + "label": "South Central US", + "value": "southcentralus" + }, + { + "label": "UK South", + "value": "uksouth" + }, + { + "label": "UK West", + "value": "ukwest" + }, + { + "label": "West Central US", + "value": "westcentralus" + }, + { + "label": "West Europe", + "value": "westeurope" + }, + { + "label": "West India", + "value": "westindia" + }, + { + "label": "West US", + "value": "westus" + }, + { + "label": "West US 2", + "value": "westus2" + } + ] + } + }, + { + "name": "avdManagementPlaneHostPoolSettings", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Host pool settings", + "elements": [ + { + "name": "hostPoolType", + "type": "Microsoft.Common.DropDown", + "visible": true, + "label": "Host pool type", + "defaultValue": "Pooled", + "multiLine": true, + "toolTip": "", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Pooled", + "description": "", + "value": "Pooled" + }, + { + "label": "Personal", + "description": "", + "value": "Personal" + } + ] + } + }, + { + "name": "subWarning", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "icon": "Warning", + "text": "Host pool type can not be changed after deployment.", + "uri": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/management-group-and-subscription-organization" + } + }, + { + "name": "loadBalancerType", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled')]", + "label": "Load balancer", + "defaultValue": "BreadthFirst", + "multiLine": true, + "toolTip": "Breadth-first load balancing distributes new user sessions across all available session hosts in the host pool. Depth-first load balancing distributes new user sessions to an available session host with the highest number of connections but has not reached its maximum session limit threshold.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "BreadthFirst", + "description": "Each new user is placed on the next VM. (Performance Optimized)", + "value": "BreadthFirst" + }, + { + "label": "DepthFirst", + "description": "Each new user is placed on the same VM until max sessions limit. (Cost Optimized)", + "value": "DepthFirst" + } + ] + } + }, + { + "name": "maxSessions", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled')]", + "label": "Max sessions", + "defaultValue": "10", + "toolTip": "The maximum number of users that have concurrent sessions on a session host. When setting a host pool to have depth first load balancing or planning to use Autoscaling, you must set an appropriate max session limit according to the configuration of your deployment and capacity of your VMs.", + "constraints": { + "required": false, + "regex": "", + "validationMessage": "" + } + }, + { + "name": "assignmentType", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Personal')]", + "label": "Machine assignment", + "defaultValue": "Automatic (Recommended)", + "multiLine": true, + "toolTip": "Automatic assignment – The service will select an available host and assign it to an user. Direct assignment – Admin selects a specific host to assign to an user.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Automatic (Recommended)", + "description": "Users are assigned an available VM the first time they connect.", + "value": "Automatic" + }, + { + "label": "Direct", + "description": "An administrator assigns a VM for each individual user.", + "value": "Direct" + } + ] + } + } + ] + }, + { + "name": "avdManagementPlaneAppGroupOptions", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType, 'Pooled')]", + "label": "Application group options (Desktop application group will be deployed by default)", + "elements": [ + { + "name": "avdDeployRAppGroup", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Create remote app group", + "defaultValue": "Yes (Recommended)", + "toolTip": "This application group type allows to publish seamless apps instead of full desktops.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes (Recommended)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + } + ] + }, + { + "name": "avdManagementPlaneHostPoolScaling", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Session host scaling options", + "elements": [ + { + "name": "startVmOnConnect", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Start VM on connect", + "defaultValue": "Yes (Recommended)", + "toolTip": "If powered off, start VM once user connects. ", + "constraints": { + "required": false, + "allowedValues": [ + { + "label": "Yes (Recommended)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "createVmRole", + "type": "Microsoft.Common.OptionsGroup", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect, true)]", + "label": "Create start VM on connect role", + "defaultValue": "Yes (Required if using Start VM On Connect)", + "toolTip": "Create custom Azure IAM role for Start VM on Connect", + "constraints": { + "required": false, + "allowedValues": [ + { + "label": "Yes (Required if using Start VM On Connect)", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdEnterApplication", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect, true)]", + "label": "AVD enterprise application ObjectID", + "defaultValue": "", + "toolTip": "Provide the ObjectID of the enterprise application Windows Virtual Desktop (ApplicationID: 9cdead84-a844-4324-93f2-b2e6bb768d07).", + "constraints": { + "required": true + } + }, + { + "name": "vmRoleWarning", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole, false)]", + "options": { + "text": "Start VM on Connect will not work without a custom role definition. If you enable start on connect, but do not specify a custom role VM's will not start on-demand. Only select no if this custom role already exists and is assigned to your AVD subscription.", + "uri": "https://docs.microsoft.com/en-us/azure/virtual-desktop/start-virtual-machine-connect", + "style": "Warning" + } + } + ] + } + ] + }, + { + "name": "avdSessionHosts", + "label": "Session Hosts", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdSessionHosts", + "elements": [ + { + "name": "avdDeploySessionHosts", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Deploy session hosts", + "defaultValue": "Yes", + "toolTip": "Create session hosts compute and storage resources.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdSessionHostsComputeStorageSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdSessionHosts').avdDeploySessionHosts, true)]", + "label": "General settings", + "tooltip": "This settings apply to compute, storage, image management and key vault resources.", + "elements": [ + { + "name": "LocationsApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "locations?api-version=2019-11-01" + } + }, + { + "name": "avdSessionHostLocation", + "type": "Microsoft.Common.DropDown", + "label": "Deployment location", + "filter": true, + "defaultValue": "East US 2", + "toolTip": "Select region where AVD session hosts (VMs), key vaults, image components and storage will be created, this location should be the closest one to the end users.", + "constraints": { + "required": true, + "allowedValues": "[map(steps('avdSessionHosts').avdSessionHostsComputeStorageSection.LocationsApi.value,(item) => parse(concat('{\"label\":\"',item.displayName,'\",\"value\":\"',item.name,'\"}')))]" + } + }, + { + "name": "avdSessionHostsAvailabilitySettings", + "type": "Microsoft.Common.OptionsGroup", + "label": "Use availability zones", + "defaultValue": "No", + "toolTip": "Distribute compute and storage resources across availability zones. When selecting No a availability set will be created to host the VMs.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + }, + { + "name": "avdStorageAccountSku", + "type": "Microsoft.Common.DropDown", + "label": "File share sku", + "filter": true, + "defaultValue": "Premium_LRS", + "toolTip": "Storage account SKU for FSLogix storage. Recommended tier is Premium_ZRS when avaiable otherwise Premium_LRS.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Premium_LRS", + "description": "", + "value": "Premium_LRS" + }, + { + "label": "Premium_ZRS (When available)", + "description": "", + "value": "Premium_ZRS" + }, + { + "label": "Standard_LRS", + "description": "", + "value": "Standard_LRS" + }, + { + "label": "Standard_ZRS (When available)", + "description": "", + "value": "Standard_ZRS" + } + ] + } + }, + { + "name": "avdSessionHostsFslogixFileShareQuota", + "type": "Microsoft.Common.Slider", + "label": "Fslogix file share size", + "subLabel": "x 100GB", + "toolTip": "Size of Premium File share storage in 10GB increments", + "min": 1, + "max": 100, + "defaultValue": 1, + "showStepMarkers": true, + "constraints": { + "required": true + } + } + ] + }, + { + "name": "avdSessionHostsSettingsSection", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdSessionHosts').avdDeploySessionHosts, true)]", + "label": "Session hosts settings", + "elements": [ + { + "name": "element1", + "type": "Microsoft.Compute.SizeSelector", + "label": "VM Size", + "toolTip": "", + "recommendedSizes": [ + "Standard_D1", + "Standard_D2", + "Standard_D3" + ], + "constraints": { + "allowedSizes": [], + "excludedSizes": [], + "required": true + }, + "options": { + "hideDiskTypeFilter": true + }, + "osPlatform": "Windows", + "imageReference": { + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-11", + "sku": "21h2-avd" + } + }, + { + "name": "avdSessionHostsCount", + "type": "Microsoft.Common.TextBox", + "label": "VM count", + "toolTip": "Provide the number of session hosts to deploy (1-499).", + "defaultValue": 1, + "constraints": { + "required": true, + "regex": "^[1-499]{1,3}$", + "validationMessage": "The count must be between 1-499 session hosts." + } + }, + { + "name": "avdSessionHostsImageSource", + "type": "Microsoft.Common.DropDown", + "label": "OS image source", + "filter": true, + "defaultValue": "Marketplace", + "toolTip": "Select marketplace or build custom image to deploy the session hosts.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Marketplace", + "value": false + }, + { + "label": "Build custom image", + "value": true + } + ] + } + }, + { + "name": "avdSessionHostsOsImage", + "type": "Microsoft.Common.DropDown", + "label": "OS version", + "filter": true, + "defaultValue": "Windows 11", + "toolTip": "Select OS version to deploy the session hosts with.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Windows 10", + "value": "win10_21h2" + }, + { + "label": "Windows 10 - Office 365", + "value": "win10_21h2_office" + }, + { + "label": "Windows 11", + "value": "win11_21h2" + }, + { + "label": "Windows 11 - Office 365", + "value": "win11_21h2_office" + } + ] + } + }, + { + "name": "avdSessionHostDiskType", + "type": "Microsoft.Common.DropDown", + "label": "OS Disk type", + "filter": true, + "defaultValue": "Standard", + "toolTip": "Select session host disk type to host the OS.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Standard", + "value": "Standard_LRS" + }, + { + "label": "Premium", + "value": "Premium_LRS" + } + ] + } + } + ] + } + ] + }, + { + "name": "avdIdentity", + "label": "Identity", + "subLabel": { + "preValidation": "", + "postValidation": "" + }, + "bladeTitle": "avdIdentitySettings", + "elements": [ + { + "name": "identityInfo", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "AVD landing zone accelerator deployment expects identity service to be already available in the current Azure estate.", + "uri": "https://docs.microsoft.com/azure/virtual-desktop/authentication#identities", + "style": "Info" + } + }, + { + "name": "avdIdentityDomainInformation", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Domain information", + "elements": [ + { + "name": "avdIdentityDomainName", + "type": "Microsoft.Common.TextBox", + "label": "Domain", + "toolTip": "Provide username with permissions to join session host to the domain.", + "placeholder": "Example: contoso.com", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityDomainOuPath", + "type": "Microsoft.Common.TextBox", + "label": "OU path (Optional)", + "toolTip": "Provide OU where to locate session hosts, if not provided session hosts will be placed on the default (computers) OU.", + "placeholder": "Example: OU=avd,DC=contoso,DC=com", + "constraints": {} + } + ] + }, + { + "name": "avdIdentityDomainCredentials", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Domain join credentials", + "elements": [ + { + "name": "avdIdentityDomainJoinUserName", + "type": "Microsoft.Common.TextBox", + "label": "Username", + "toolTip": "Provide username with permissions to join session host to the domain.", + "placeholder": "Example: avdadmin@contoso.com", + "defaultValue": "", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityDomainJoinUserPassword", + "type": "Microsoft.Compute.CredentialsCombo", + "visible": true, + "label": { + "password": "Password", + "confirmPassword": "Confirm password" + }, + "toolTip": { + "password": "" + }, + "constraints": { + "required": true + }, + "options": { + "hideConfirmation": true + }, + "osPlatform": "Windows" + } + ] + }, + { + "name": "avdIdentityLocalCredentials", + "type": "Microsoft.Common.Section", + "visible": true, + "label": "Session host local admin credentials", + "elements": [ + { + "name": "avdIdentityLocalUserName", + "type": "Microsoft.Common.TextBox", + "label": "Username", + "toolTip": "Provide username for session host local admin account.", + "placeholder": "Example: avdadmin", + "defaultValue": "", + "constraints": { + "required": true + } + }, + { + "name": "avdIdentityLocalUserPassword", + "type": "Microsoft.Compute.CredentialsCombo", + "visible": true, + "label": { + "password": "Password", + "confirmPassword": "Confirm password" + }, + "toolTip": { + "password": "The password must be alphanumeric, contain at least 12 characters, have at least 1 letter,1 number and 1 special character." + }, + "constraints": { + "required": true, + "customPasswordRegex": "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=_!*<>()])(?=\\S+$).{12,123}$", + "customValidationMessage": "Password must include 1 special character." + }, + "options": { + "hideConfirmation": false + }, + "osPlatform": "Windows" + } + ] + } + ] + }, + { + "name": "avdNetwork", + "label": "Network connectivity", + "type": "Microsoft.Common.Section", + "visible": true, + "elements": [ + { + "name": "vnetInfoBox", + "type": "Microsoft.Common.InfoBox", + "visible": true, + "options": { + "text": "AVD landing zone accelerator requires connectivity to identity services (ADDS or AADDS).", + "uri": "https://docs.microsoft.com/azure/virtual-desktop/network-connectivity", + "style": "info" + } + }, + { + "name": "createAvdVnet", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Virtual network", + "defaultValue": "New", + "toolTip": "", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "New", + "value": true + }, + { + "label": "Existing", + "value": false + } + ] + } + }, + { + "name": "avdVnetSize", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "vNet address range", + "toolTip": "Virtual network for AVD virtual machines", + "placeholder": "Example: 10.10.0.0/23", + "constraints": { + "required": true, + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "validationMessage": "Invalid CIDR range. The address prefix must be in the range 10 to 24." + } + }, + { + "name": "avdVnetSubnetSize", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "Subnet address prefix", + "toolTip": "Virtual network subnet for AVD virtual machines", + "placeholder": "Example: 10.10.0.0/23", + "constraints": { + "required": true, + "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-4]))$", + "validationMessage": "Invalid CIDR range. The address prefix must be in the range 10 to 24." + } + }, + { + "name": "avdVnetDns", + "type": "Microsoft.Common.TextBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "vNet DNS Servers", + "defaultValue": "", + "placeholder": "Example: 10.10.100.4, 10.20.100.5", + "toolTip": "If using custom DNS servers, enter multiple IPs separated by a comma.", + "constraints": { + "required": true, + "regex": "" + } + }, + { + "name": "avdVnetPeeringInfoBox", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "options": { + "text": "vNet peering will be created to existing vNet hub with access to identity and DNS services .", + "uri": "https://docs.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?context=/azure/virtual-desktop/context/context", + "style": "info" + } + }, + { + "name": "avdHubVnetPeering", + "type": "Microsoft.Common.Section", + "visible": "[equals(steps('avdNetwork').createAvdVnet, true)]", + "label": "Existing hub vNet peering information", + "elements": [ + { + "name": "avdHubVnetSelector", + "type": "Microsoft.Solutions.ResourceSelector", + "label": "Virtual Network", + "resourceType": "Microsoft.Network/virtualNetworks", + "constraints": { + "required": true + } + }, + { + "name": "avdHubVnetGateway", + "type": "Microsoft.Common.OptionsGroup", + "visible": true, + "label": "Gateway on hub", + "defaultValue": "No", + "toolTip": "This information will be used to set remote gateway settings on vNet peering.", + "constraints": { + "required": true, + "allowedValues": [ + { + "label": "Yes", + "value": true + }, + { + "label": "No", + "value": false + } + ] + } + } + ] + }, + { + "name": "avdExistingVnetInfoBox", + "type": "Microsoft.Common.InfoBox", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "options": { + "text": "Existing network must has connectivity to identity and DNS services.", + "uri": "https://docs.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?context=/azure/virtual-desktop/context/context", + "style": "info" + } + }, + { + "name": "avdVnetSelectorId", + "type": "Microsoft.Solutions.ResourceSelector", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "label": "Virtual network", + "resourceType": "Microsoft.Network/virtualNetworks", + "constraints": { + "required": true + } + }, + { + "name": "avdSubnetApi", + "type": "Microsoft.Solutions.ArmApiControl", + "request": { + "method": "GET", + "path": "[concat(steps('avdNetwork').avdVnetSelectorId.id, '/subnets?api-version=2021-03-01')]" + } + }, + { + "name": "avdVnetSubnetSelectorName", + "label": "Subnet", + "type": "Microsoft.Common.DropDown", + "visible": "[equals(steps('avdNetwork').createAvdVnet, false)]", + "defaultValue": "", + "toolTip": "Select the subnet.", + "multiselect": false, + "selectAll": false, + "filter": true, + "filterPlaceholder": "Filter items ...", + "multiLine": true, + "constraints": { + "allowedValues": "[map(steps('avdNetwork').avdSubnetApi.value,(item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\",\"description\":\"', 'Resource Group: ', last(take(split(item.id, '/'), 5)), '\"}')))]", + "required": true + } + } + ] + } + ] + }, + "outputs": { + "parameters": { + "deploymentPrefix": "[steps('avdLzSettings').avdDeploymentPrefix]", + "avdSessionHostLocation": "[steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdSessionHostLocation]", + "fsLogixstorageSku": "[steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdStorageAccountSku]", + "avdManagementPlaneLocation": "[steps('avdManagementPlane').avdManagementPlaneLocation]", + "avdSubOrgsOption": "[steps('avdLzSettings').avdSubOrgsOption]", + "avdSingleSubsId": "[steps('avdLzSettings').avdSingleSubSection.avdSingleSub.subscriptionId]", + "avdShrdlSubsId": "[steps('avdLzSettings').avdMultipleSubSection.avdMultipleSubShared.subscriptionId]", + "avdWrklSubsId": "[steps('avdLzSettings').avdMultipleSubSection.avdMultipleSubWorkload.subscriptionId]", + "avdHostPoolType": "[steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.hostPoolType]", + "avdHostPoolloadBalancerType": "[steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.loadBalancerType]", + "avhHostPoolMaxSessions": "[steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.maxSessions]", + "avdPersonalAssignType": "[steps('avdManagementPlane').avdManagementPlaneHostPoolSettings.assignmentType]", + "avdDeployRAppGroup": "[steps('avdManagementPlane').avdManagementPlaneAppGroupOptions.avdDeployRAppGroup]", + "createVmRole": "[steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole]", + "avdIdentityDomainName": "[steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainName]", + "avdOuPath": "[steps('avdIdentity').avdIdentityDomainInformation.avdIdentityDomainOuPath]", + "avdDomainJoinUserName": "[steps('avdIdentity').avdIdentityDomainCredentials.avdIdentityDomainJoinUserName]", + "avdDomainJoinUserPassword": "[steps('avdIdentity').avdIdentityDomainCredentials.avdIdentityDomainJoinUserPassword.password]", + "avdVmLocalUserName": "[steps('avdIdentity').avdIdentityLocalCredentials.avdIdentityLocalUserName]", + "avdVmLocalUserPassword": "[steps('avdIdentity').avdIdentityLocalCredentials.avdIdentityLocalUserPassword.password]", + "createAvdVnet": "[steps('avdNetwork').createAvdVnet]", + "avdVnetworkAddressPrefixes": "[[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdVnetSize, '')]", + "avdVnetworkSubnetAddressPrefix": "[[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdVnetSubnetSize, '')]", + "customDnsIps": "[[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdVnetDns, '')]", + "existingHubVnetResourceId": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdHubVnetPeering.avdHubVnetSelector.id, '')]", + "vNetworkGatewayOnHub": "[if(equals(steps('avdNetwork').createAvdVnet, true), steps('avdNetwork').avdHubVnetPeering.avdHubVnetGateway, false)]", + "existingVnetSubnetResourceId": "[if(equals(steps('avdNetwork').createAvdVnet, false), steps('avdNetwork').avdVnetSubnetSelectorName, '')]", + "avdDeploySessionHosts": "[steps('avdSessionHosts').avdDeploySessionHosts]", + "avdStartVMOnConnect": "[steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect]", + "createStartVmOnConnectCustomRole": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.startVmOnConnect, true), steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole, '')]", + "avdEnterpriseAppObjectId": "[if(equals(steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.createVmRole, true), steps('avdManagementPlane').avdManagementPlaneHostPoolScaling.avdEnterApplication.objectId, '')]", + "avdUseAvailabilityZones": "[steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdSessionHostsAvailabilitySettings]", + "avdDeploySessionHostsCount": "[if(equals(steps('avdSessionHosts').avdDeploySessionHosts, true), steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostsCount, 1)]", + "useSharedImage": "[if(equals(steps('avdSessionHosts').avdDeploySessionHosts, true), steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostsImageSource, false)]", + "avdOsImage": "[steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostsOsImage]", + "avdSessionHostDiskType": "[steps('avdSessionHosts').avdSessionHostsSettingsSection.avdSessionHostDiskType]", + "avdSessionHostsSize": "[steps('avdSessionHosts').avdSessionHostsSettingsSection.element1]", + "avdFslogixFileShareQuotaSize": "[steps('avdSessionHosts').avdSessionHostsComputeStorageSection.avdSessionHostsFslogixFileShareQuota]" + }, + "kind": "Tenant", + "location": "[steps('basics').resourceScope.location.name]" + } + } +} \ No newline at end of file diff --git a/workload/scripts/DSCDomainJoinStorageScripts.zip b/workload/scripts/DSCDomainJoinStorageScripts.zip new file mode 100644 index 000000000..884edd907 Binary files /dev/null and b/workload/scripts/DSCDomainJoinStorageScripts.zip differ diff --git a/workload/scripts/Manual-DSC-JoinStorage-to-ADDS.ps1 b/workload/scripts/Manual-DSC-JoinStorage-to-ADDS.ps1 new file mode 100644 index 000000000..72c839369 --- /dev/null +++ b/workload/scripts/Manual-DSC-JoinStorage-to-ADDS.ps1 @@ -0,0 +1,72 @@ +param ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $DscPath, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $StorageAccountName, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $StorageAccountRG, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $ShareName, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $DomainName, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $AzureCloudEnvironment, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $OUName, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $CreateNewOU, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $DomainAdminUserName, + + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string] $DomainAdminUserPassword + +) +Write-Host "Downloading the DSCDomainJoinStorageScripts.zip from $DscPath" +$DscArhive="DSCDomainJoinStorageScripts.zip" +$appName = 'DSCDomainJoinStorageScripts' +$drive = 'C:\Packages' +New-Item -Path $drive -Name $appName -ItemType Directory -ErrorAction SilentlyContinue +$LocalPath = "C:\Packages\DSCDomainJoinStorageScripts" +$OutputPath = $LocalPath + '\' + $DscArhive +Invoke-WebRequest -Uri $DscPath -OutFile $OutputPath + +Write-Host "Expanding the archive $DscArchive" +Expand-Archive -LiteralPath 'C:\\Packages\\DSCDomainJoinStorageScripts\\DSCDomainJoinStorageScripts.zip' -DestinationPath $Localpath -Force -Verbose + +Set-Location -Path $LocalPath + +Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force +Install-Module 'PSDscResources' -Force + + +$DscCompileCommand="./Configuration.ps1 -StorageAccountName " + $StorageAccountName + " -StorageAccountRG " + $StorageAccountRG + " -ShareName " + $ShareName + " -DomainName " + $DomainName + " -AzureCloudEnvironment " + $AzureCloudEnvironment + " -OUName " + $OUName + " -CreateNewOU " + $CreateNewOU + " -DomainAdminUserName " + $DomainAdminUserName + " -DomainAdminUserPassword " + $DomainAdminUserPassword + " -Verbose" + +Write-Host "Executing the commmand $DscCompileCommand" +Invoke-Expression -Command $DscCompileCommand + +$MofFolder='DomainJoinFileShare' +$MofPath=$LocalPath + '\' + $MofFolder +Write-Host "Generated MOF files here: $MofPath" + +Write-Host "Applying MOF files. DSC configuration" +Set-WSManQuickConfig -Force -Verbose +Start-DscConfiguration -Path $MofPath -Wait -Verbose diff --git a/workload/scripts/Optimize_OS_for_AVD.ps1 b/workload/scripts/Optimize_OS_for_AVD.ps1 new file mode 100644 index 000000000..b52b36b86 --- /dev/null +++ b/workload/scripts/Optimize_OS_for_AVD.ps1 @@ -0,0 +1,88 @@ +# OS Optimizations for WVD +Write-Host 'AIB Customization: OS Optimizations for WVD' +$appName = 'optimize' +$drive = 'C:\' +New-Item -Path $drive -Name $appName -ItemType Directory -ErrorAction SilentlyContinue +$LocalPath = $drive + '\' + $appName +Set-Location $LocalPath +Write-Host 'Created the local directory' +$osOptURL = 'https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool/archive/refs/heads/main.zip' +$osOptURLexe = 'Windows_10_VDI_Optimize-main.zip' +$outputPath = $LocalPath + '\' + $osOptURLexe +Write-Host 'Loading up the repo to local folder' +Invoke-WebRequest -Uri $osOptURL -OutFile $outputPath +Write-Host 'AIB Customization: Starting OS Optimizations script' +Expand-Archive -LiteralPath 'C:\\Optimize\\Windows_10_VDI_Optimize-main.zip' -DestinationPath $Localpath -Force -Verbose +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process +Set-Location -Path C:\\Optimize\\Virtual-Desktop-Optimization-Tool-main + +# instrumentation +$osOptURL = 'https://raw.githubusercontent.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool/main/Win10_VirtualDesktop_Optimize.ps1' +$osOptURLexe = 'optimize.ps1' +Invoke-WebRequest -Uri $osOptURL -OutFile $osOptURLexe + +# Patch: overide the Win10_VirtualDesktop_Optimize.ps1 - setting 'Set-NetAdapterAdvancedProperty'(see readme.md) +Write-Host 'Patch: Disabling Set-NetAdapterAdvancedProperty' +$updatePath = 'C:\optimize\Virtual-Desktop-Optimization-Tool-main\Win10_VirtualDesktop_Optimize.ps1' + ((Get-Content -Path $updatePath -Raw) -replace 'Set-NetAdapterAdvancedProperty -DisplayName "Send Buffer Size" -DisplayValue 4MB', '#Set-NetAdapterAdvancedProperty -DisplayName "Send Buffer Size" -DisplayValue 4MB') | Set-Content -Path $updatePath + + + +Write-Host 'Patch: Disabling Set-NetAdapterAdvancedProperty in Windows_VDOT.ps1' +$updatePath = 'C:\optimize\Virtual-Desktop-Optimization-Tool-main\Windows_VDOT.ps1' + ((Get-Content -Path $updatePath -Raw) -replace 'Set-NetAdapterAdvancedProperty -DisplayName "Send Buffer Size" -DisplayValue 4MB', '#Set-NetAdapterAdvancedProperty -DisplayName "Send Buffer Size" -DisplayValue 4MB') | Set-Content -Path $updatePath + + +# Patch: overide the REG UNLOAD, needs GC before, otherwise will Access Deny unload(see readme.md) + +[System.Collections.ArrayList]$file = Get-Content $updatePath +$insert = @() +for ($i = 0; $i -lt $file.count; $i++) { + if ($file[$i] -like '*& REG UNLOAD HKLM\DEFAULT*') { + $insert += $i - 1 + } +} + +#add gc and sleep +$insert | ForEach-Object { $file.insert($_, " Write-Host 'Patch closing handles and runnng GC before reg unload' `n `$newKey.Handle.close()` `n [gc]::collect() `n Start-Sleep -Seconds 15 ") } + +### Setting the RDP Shortpath. +Write-Host 'Configuring RDP ShortPath' + +$WinstationsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations' + +if (Test-Path $WinstationsKey) { + New-ItemProperty -Path $WinstationsKey -Name 'fUseUdpPortRedirector' -ErrorAction:SilentlyContinue -PropertyType:dword -Value 1 -Force + New-ItemProperty -Path $WinstationsKey -Name 'UdpPortNumber' -ErrorAction:SilentlyContinue -PropertyType:dword -Value 3390 -Force +} + +Write-Host 'Settin up the Windows Firewall Rue for RDP ShortPath' +New-NetFirewallRule -DisplayName 'Remote Desktop - Shortpath (UDP-In)' -Action Allow -Description 'Inbound rule for the Remote Desktop service to allow RDP traffic. [UDP 3390]' -Group '@FirewallAPI.dll,-28752' -Name 'RemoteDesktop-UserMode-In-Shortpath-UDP' -PolicyStore PersistentStore -Profile Domain, Private -Service TermService -Protocol udp -LocalPort 3390 -Program '%SystemRoot%\system32\svchost.exe' -Enabled:True + +### Setting the Screen Protection + +Write-Host 'Configuring Screen Protection' + +$WinstationsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations' + +if (Test-Path $WinstationsKey) { + New-ItemProperty -Path $WinstationsKey -Name 'fEnableScreenCaptureProtect' -ErrorAction:SilentlyContinue -PropertyType:dword -Value 1 -Force +} + +Set-Content $updatePath $file + +# run script +# .\optimize -WindowsVersion 2004 -Verbose +.\Win10_VirtualDesktop_Optimize.ps1 -Verbose -AcceptEULA +Write-Host 'AIB Customization: Finished OS Optimizations script Win10_VirtualDesktop_Optimize.ps1' + +# Sleep for a min +Start-Sleep -Seconds 60 +#Running new file + +#Write-Host 'Running new AIB Customization script' +.\Windows_VDOT.ps1 -Verbose -AcceptEULA +Write-Host 'AIB Customization: Finished OS Optimizations script Windows_VDOT.ps1' + + + diff --git a/workload/scripts/Set-FSLogixRegKeys.ps1 b/workload/scripts/Set-FSLogixRegKeys.ps1 new file mode 100644 index 000000000..e7c4898aa --- /dev/null +++ b/workload/scripts/Set-FSLogixRegKeys.ps1 @@ -0,0 +1,13 @@ +param( + [string]$volumeshare +) + + +reg.exe add 'HKEY_LOCAL_MACHINE\Software\FSLogix\Profiles' /v VHDLocations /t REG_MULTI_SZ /d $volumeshare /f + +reg.exe add 'HKEY_LOCAL_MACHINE\Software\FSLogix\Profiles' /v DeleteLocalProfileWhenVHDShouldApply /t REG_DWORD /d 1 /f + +reg.exe add 'HKEY_LOCAL_MACHINE\Software\FSLogix\Profiles' /v FlipFlopProfileDirectoryName /t REG_DWORD /d 1 /f + +reg.exe add 'HKEY_LOCAL_MACHINE\Software\FSLogix\Profiles' /v Enabled /t REG_DWORD /d 1 /f + diff --git a/workload/scripts/rdpshortpath.ps1 b/workload/scripts/rdpshortpath.ps1 new file mode 100644 index 000000000..f097c5cd6 --- /dev/null +++ b/workload/scripts/rdpshortpath.ps1 @@ -0,0 +1,20 @@ +$WinstationsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations' + +if(Test-Path $WinstationsKey){ + New-ItemProperty -Path $WinstationsKey -Name 'fUseUdpPortRedirector' -ErrorAction:SilentlyContinue -PropertyType:dword -Value 1 -Force + New-ItemProperty -Path $WinstationsKey -Name 'UdpPortNumber' -ErrorAction:SilentlyContinue -PropertyType:dword -Value 3390 -Force +} + +New-NetFirewallRule ` + -DisplayName 'Remote Desktop - Shortpath (UDP-In)' ` + -Action Allow ` + -Description 'Inbound rule for the Remote Desktop service to allow RDP traffic. [UDP 3390]' ` + -Group '@FirewallAPI.dll,-28752' ` + -Name 'RemoteDesktop-UserMode-In-Shortpath-UDP' ` + -PolicyStore PersistentStore ` + -Profile Domain, Private ` + -Service TermService ` + -Protocol udp ` + -LocalPort 3390 ` + -Program '%SystemRoot%\system32\svchost.exe' + `-Enabled:True \ No newline at end of file diff --git a/workload/scripts/screencaptureprotection.ps1 b/workload/scripts/screencaptureprotection.ps1 new file mode 100644 index 000000000..880929e99 --- /dev/null +++ b/workload/scripts/screencaptureprotection.ps1 @@ -0,0 +1,6 @@ + +$WinstationsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations' + +if(Test-Path $WinstationsKey){ + New-ItemProperty -Path $WinstationsKey -Name 'fEnableScreenCaptureProtect' -ErrorAction:SilentlyContinue -PropertyType:dword -Value 1 -Force +} \ No newline at end of file diff --git a/workload/vm-custom-extensions/add-avd-session-hosts.bicep b/workload/vm-custom-extensions/add-avd-session-hosts.bicep new file mode 100644 index 000000000..a4fe34781 --- /dev/null +++ b/workload/vm-custom-extensions/add-avd-session-hosts.bicep @@ -0,0 +1,32 @@ +param name string +param location string +param avdAgentPackageLocation string +param hostPoolName string +param systemData object = {} + + +//@secure() +param hostPoolToken string + +/* Add session hosts to Host Pool */ + +resource addToHostPool 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/Microsoft.PowerShell.DSC' + location: location + properties: { + publisher: 'Microsoft.PowerShell' + type: 'DSC' + typeHandlerVersion: '2.73' + autoUpgradeMinorVersion: true + settings: { + modulesUrl: avdAgentPackageLocation + configurationFunction: 'Configuration.ps1\\AddSessionHost' + properties: { + hostPoolName: hostPoolName + registrationInfoToken: hostPoolToken + aadJoin: false + sessionHostConfigurationLastUpdateTime: contains(systemData,'hostpoolUpdate') ? systemData.sessionHostConfigurationVersion : '' + } + } + } +} diff --git a/workload/vm-custom-extensions/add-azure-files-to-adds-script.bicep b/workload/vm-custom-extensions/add-azure-files-to-adds-script.bicep new file mode 100644 index 000000000..57fe7b040 --- /dev/null +++ b/workload/vm-custom-extensions/add-azure-files-to-adds-script.bicep @@ -0,0 +1,22 @@ +param name string +param location string +param baseScriptUri string +param file string +@secure() +param ScriptArguments string + +resource addAzureFilesToADDSScript 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/addAzureFilesToADDSScript' + location: location + properties: { + publisher: 'Microsoft.Compute' + type: 'CustomScriptExtension' + typeHandlerVersion: '1.10' + autoUpgradeMinorVersion: true + settings: {} + protectedSettings: { + fileUris: array(baseScriptUri) + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File ${file} ${ScriptArguments}' + } + } +} diff --git a/workload/vm-custom-extensions/add-azure-files-to-adds.bicep b/workload/vm-custom-extensions/add-azure-files-to-adds.bicep new file mode 100644 index 000000000..129702d3b --- /dev/null +++ b/workload/vm-custom-extensions/add-azure-files-to-adds.bicep @@ -0,0 +1,46 @@ +param name string +param location string +param dscAgentPackageLocation string +param storageAccountName string +param storageAccountRG string +param domainName string +param AzureCloudEnvironment string + + + +@secure() +param domainAdminPassword string + +param domainAdminUsername string + +/* Add Azure Files to AD DS domain*/ + +resource addAzureFilesToADDS 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/Microsoft.PowerShell.DSC' + location: location + properties: { + publisher: 'Microsoft.PowerShell' + type: 'DSC' + typeHandlerVersion: '2.73' + autoUpgradeMinorVersion: true + settings: { + configuration: { + url: dscAgentPackageLocation + script: 'Configuration.ps1' + function: 'DomainJoinFileShare' + } + configurationArguments: { + storageAccountName: storageAccountName + storageAccountRG: storageAccountRG + DomainName: domainName + AzureCloudEnvironment: AzureCloudEnvironment + DomainAdminUserName: domainAdminUsername + } + } + protectedSettings: { + configurationArguments: { + DomainAdminUserPassword: domainAdminPassword + } + } + } +} diff --git a/workload/vm-custom-extensions/configure-fslogix-session-hosts.bicep b/workload/vm-custom-extensions/configure-fslogix-session-hosts.bicep new file mode 100644 index 000000000..d62de4404 --- /dev/null +++ b/workload/vm-custom-extensions/configure-fslogix-session-hosts.bicep @@ -0,0 +1,21 @@ +param name string +param location string +param baseScriptUri string +param file string +param FsLogixScriptArguments string + +resource fslogixconfigure 'Microsoft.Compute/virtualMachines/extensions@2021-07-01' = { + name: '${name}/configurefslogix' + location: location + properties: { + publisher: 'Microsoft.Compute' + type: 'CustomScriptExtension' + typeHandlerVersion: '1.10' + autoUpgradeMinorVersion: true + settings: {} + protectedSettings: { + fileUris: array(baseScriptUri) + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File ${file} ${FsLogixScriptArguments}' + } + } +}